You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fop-commits@xmlgraphics.apache.org by je...@apache.org on 2003/03/27 12:10:34 UTC

cvs commit: xml-fop/src/java/org/apache/fop/pdf PDFEncryptionJCE.java PDFEncryption.java

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: fop-cvs-unsubscribe@xml.apache.org
For additional commands, e-mail: fop-cvs-help@xml.apache.org