jeremias    2003/03/27 03:10:33

  Modified:    src/java/org/apache/fop/pdf PDFEncryptionJCE.java
                        PDFEncryption.java
  Log:
  PDF Encryption works now in every case I tested. Also, the text and string 
dictionary entries of PDFInfo are encrypted. The rest of these value still need to be 
done (best done in one task with refactoring PDF dict generation).
  Bring back support for encrypting byte arrays.
  
  Revision  Changes    Path
  1.2       +78 -49    xml-fop/src/java/org/apache/fop/pdf/PDFEncryptionJCE.java
  
  Index: PDFEncryptionJCE.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/java/org/apache/fop/pdf/PDFEncryptionJCE.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- PDFEncryptionJCE.java     13 Mar 2003 16:46:05 -0000      1.1
  +++ PDFEncryptionJCE.java     27 Mar 2003 11:10:33 -0000      1.2
  @@ -54,12 +54,12 @@
   import java.io.InputStream;
   import java.io.OutputStream;
   import java.io.IOException;
  -import java.io.UnsupportedEncodingException;
   import java.security.MessageDigest;
   import java.security.NoSuchAlgorithmException;
   import java.security.InvalidKeyException;
   import javax.crypto.Cipher;
   import javax.crypto.spec.SecretKeySpec;
  +import javax.crypto.CipherOutputStream;
   import javax.crypto.IllegalBlockSizeException;
   import javax.crypto.BadPaddingException;
   import javax.crypto.NoSuchPaddingException;
  @@ -89,6 +89,8 @@
               this.encryption = encryption;
               this.number  = number;
               this.generation = generation;
  +            //System.out.println("new encryption filter for number "
  +            //    +number+" and generation "+generation);
           }
   
           /** 
  @@ -128,6 +130,14 @@
               out.write(buffer);
           }
           
  +        /**
  +         * @see org.apache.fop.pdf.PDFFilter#applyFilter(OutputStream)
  +         */
  +        public OutputStream applyFilter(OutputStream out) throws IOException {
  +            return new CipherOutputStream(out, 
  +                    encryption.initCipher(number, generation));
  +        }
  +
       }
   
       private static final char [] PAD = 
  @@ -135,9 +145,6 @@
                                    0x64, 0x00, 0x4E, 0x56, 0xFF, 0xFA, 0x01, 0x08, 
                                    0x2E, 0x2E, 0x00, 0xB6, 0xD0, 0x68, 0x3E, 0x80, 
                                    0x2F, 0x0C, 0xA9, 0xFE, 0x64, 0x53, 0x69, 0x7A };
  -    private static final char[] DIGITS = 
  -                                 {'0', '1', '2', '3', '4', '5', '6', '7',
  -                                  '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
                                     
       /** Value of PRINT permission */                                  
       public static final int PERMISSION_PRINT            =  4;
  @@ -150,7 +157,7 @@
       
       // Encryption tools
       private MessageDigest digest = null;
  -    private Cipher cipher = null;
  +    //private Cipher cipher = null;
       private Random random = new Random();
       // Control attributes
       private PDFEncryptionParams params;
  @@ -160,20 +167,21 @@
       private String dictionary = null;
   
       /**
  -     * create a /Filter /Standard object.
  +     * Create a /Filter /Standard object.
        *
  -     * @param number the object's number
  +     * @param objnum the object's number
        */
  -    public PDFEncryptionJCE(int number) {
  +    public PDFEncryptionJCE(int objnum) {
           /* generic creation of object */
  -        super(number);
  +        super();
  +        setObjectNumber(objnum);
           try {
               digest = MessageDigest.getInstance("MD5");
  -            cipher = Cipher.getInstance("RC4");
  +            //cipher = Cipher.getInstance("RC4");
           } catch (NoSuchAlgorithmException e) {
               throw new UnsupportedOperationException(e.getMessage());
  -        } catch (NoSuchPaddingException e) {
  -            throw new UnsupportedOperationException(e.getMessage());
  +        /*} catch (NoSuchPaddingException e) {
  +            throw new UnsupportedOperationException(e.getMessage());*/
           }
       }
   
  @@ -227,17 +235,6 @@
           return obuffer;
       }
   
  -    private String toHex(byte[] value) {
  -        StringBuffer buffer = new StringBuffer();
  -        
  -        for (int i = 0; i < value.length; i++) {
  -            buffer.append(DIGITS[(value[i] >>> 4) & 0x0F]);
  -            buffer.append(DIGITS[value[i] & 0x0F]);
  -        }
  -        
  -        return buffer.toString();
  -    }
  -    
       /** 
        * Returns the document file ID
        * @return The file ID
  @@ -258,38 +255,63 @@
        */    
       public String getFileID(int index) {
           if (index == 1) {
  -            return toHex(getFileID());
  +            return PDFText.toHex(getFileID());
           }
           
           byte[] id = new byte[16];
           random.nextBytes(id);
  -        return toHex(id);
  +        return PDFText.toHex(id);
       }
           
       private byte[] encryptWithKey(byte[] data, byte[] key) {
           try {
  -            SecretKeySpec keyspec = new SecretKeySpec(key, "RC4");
  -            cipher.init(Cipher.ENCRYPT_MODE, keyspec);
  -            return cipher.doFinal(data);
  +            final Cipher c = initCipher(key);
  +            return c.doFinal(data);
           } catch (IllegalBlockSizeException e) {
               throw new IllegalStateException(e.getMessage());
           } catch (BadPaddingException e) {
               throw new IllegalStateException(e.getMessage());
  +        }
  +    }
  +    
  +    private Cipher initCipher(byte[] key) {
  +        try {
  +            Cipher c = Cipher.getInstance("RC4");
  +            SecretKeySpec keyspec = new SecretKeySpec(key, "RC4");
  +            c.init(Cipher.ENCRYPT_MODE, keyspec);
  +            return c;
           } catch (InvalidKeyException e) {
               throw new IllegalStateException(e.getMessage());
  +        } catch (NoSuchAlgorithmException e) {
  +            throw new UnsupportedOperationException(e.getMessage());
  +        } catch (NoSuchPaddingException e) {
  +            throw new UnsupportedOperationException(e.getMessage());
           }
       }
       
  +    private Cipher initCipher(int number, int generation) {
  +        byte[] hash = calcHash(number, generation);
  +        int size = hash.length;
  +        hash = digest.digest(hash);
  +        byte[] key = calcKey(hash, size);
  +        return initCipher(key);
  +    }
  +    
       private byte[] encryptWithHash(byte[] data, byte[] hash, int size) {
           hash = digest.digest(hash);
  +
  +        byte[] key = calcKey(hash, size);        
           
  +        return encryptWithKey(data, key);
  +    }
  +
  +    private byte[] calcKey(byte[] hash, int size) {
           byte[] key = new byte[size];
   
           for (int i = 0; i < size; i++) {
               key[i] = hash[i];
           }
  -        
  -        return encryptWithKey(data, key);
  +        return key;
       }
   
       /** 
  @@ -344,14 +366,14 @@
           byte[] uValue = encryptWithKey(prepPassword(""), this.encryptionKey);
           
           // Create the dictionary
  -        this.dictionary = this.number + " " + this.generation
  -                        + " obj\n<< /Filter /Standard\n"
  +        this.dictionary = getObjectID() 
  +                        + "<< /Filter /Standard\n"
                           + "/V 1\n"
                           + "/R 2\n"
                           + "/Length 40\n"
                           + "/P "  + permissions + "\n"
  -                        + "/O <" + toHex(oValue) + ">\n"
  -                        + "/U <" + toHex(uValue) + ">\n"
  +                        + "/O " + PDFText.toHex(oValue) + "\n"
  +                        + "/U " + PDFText.toHex(uValue) + "\n"
                           + ">>\n"
                           + "endobj\n";
       }
  @@ -367,11 +389,23 @@
           if (this.encryptionKey == null) {
               throw new IllegalStateException("PDF Encryption has not been 
initialized");
           }
  -        
  +        //getDocument().getLogger().debug("encrypting with for "+number+" 
"+generation);
  +
  +        byte[] hash = calcHash(number, generation);        
  +        return encryptWithHash(data, hash, hash.length);
  +    }
  +
  +    /**
  +     * @see org.apache.fop.pdf.PDFEncryption#encrypt(byte[], PDFObject)
  +     */
  +    public byte[] encrypt(byte[] data, PDFObject refObj) {
  +        return encryptData(data, refObj.getObjectNumber(), refObj.getGeneration());
  +    }
  +
  +    private byte[] calcHash(int number, int generation) {
           byte[] hash = new byte[this.encryptionKey.length + 5];
               
           int i = 0;
  -            
           while (i < this.encryptionKey.length) {
               hash[i] = this.encryptionKey[i]; i++;
           }
  @@ -381,8 +415,7 @@
           hash[i++] = (byte) (number >>> 16);
           hash[i++] = (byte) (generation >>> 0);
           hash[i++] = (byte) (generation >>> 8);;
  -        
  -        return encryptWithHash(data, hash, hash.length);
  +        return hash;        
       }
   
       /** 
  @@ -399,8 +432,9 @@
        * Adds a PDFFilter to the PDFStream object
        * @param stream the stream to add an encryption filter to
        */    
  -    public void applyFilter(PDFStream stream) {
  -        stream.addFilter(this.makeFilter(stream.number, stream.generation));
  +    public void applyFilter(AbstractPDFStream stream) {
  +        stream.getFilterList().addFilter(
  +                this.makeFilter(stream.getObjectNumber(), stream.getGeneration()));
       }
       
       /**
  @@ -413,20 +447,15 @@
               throw new IllegalStateException("PDF Encryption has not been 
initialized");
           }
           
  -        try {
  -            return this.dictionary.getBytes(PDFDocument.ENCODING);
  -        } catch (UnsupportedEncodingException ue) {
  -            return this.dictionary.getBytes();
  -        }       
  +        return encode(this.dictionary);
       }
   
       /**
        * @see org.apache.fop.pdf.PDFEncryption#getTrailerEntry()
        */
       public String getTrailerEntry() {
  -        return "/Encrypt " + number + " " 
  -                    + generation + " R\n"
  -                    + "/ID[<" + getFileID(1) + "><"
  -                    + getFileID(2) + ">]\n";
  +        return "/Encrypt " + getObjectNumber() + " " 
  +                    + getGeneration() + " R\n"
  +                    + "/ID[" + getFileID(1) + getFileID(2) + "]\n";
       }
   }
  
  
  
  1.2       +10 -1     xml-fop/src/java/org/apache/fop/pdf/PDFEncryption.java
  
  Index: PDFEncryption.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/java/org/apache/fop/pdf/PDFEncryption.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- PDFEncryption.java        13 Mar 2003 16:46:05 -0000      1.1
  +++ PDFEncryption.java        27 Mar 2003 11:10:33 -0000      1.2
  @@ -71,7 +71,16 @@
        * Adds a PDFFilter to the PDFStream object
        * @param stream the stream to add an encryption filter to
        */    
  -    void applyFilter(PDFStream stream);
  +    void applyFilter(AbstractPDFStream stream);
  + 
  +    /**
  +     * Encrypt an array of bytes using a reference PDFObject for calculating
  +     * the encryption key.
  +     * @param data data to encrypt
  +     * @param refObj reference PDFObject
  +     * @return byte[] the encrypted data
  +     */
  +    byte[] encrypt(byte[] data, PDFObject refObj);
    
       /**
        * Returns the trailer entry for encryption.
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to