diff options
Diffstat (limited to 'src/java/org/apache')
-rw-r--r-- | src/java/org/apache/fop/pdf/PDFEncryption.java | 11 | ||||
-rw-r--r-- | src/java/org/apache/fop/pdf/PDFEncryptionJCE.java | 127 |
2 files changed, 88 insertions, 50 deletions
diff --git a/src/java/org/apache/fop/pdf/PDFEncryption.java b/src/java/org/apache/fop/pdf/PDFEncryption.java index e0ad29552..82402090c 100644 --- a/src/java/org/apache/fop/pdf/PDFEncryption.java +++ b/src/java/org/apache/fop/pdf/PDFEncryption.java @@ -71,7 +71,16 @@ public interface PDFEncryption { * 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. diff --git a/src/java/org/apache/fop/pdf/PDFEncryptionJCE.java b/src/java/org/apache/fop/pdf/PDFEncryptionJCE.java index affcc2f68..954ca2801 100644 --- a/src/java/org/apache/fop/pdf/PDFEncryptionJCE.java +++ b/src/java/org/apache/fop/pdf/PDFEncryptionJCE.java @@ -54,12 +54,12 @@ package org.apache.fop.pdf; 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 @@ public class PDFEncryptionJCE extends PDFObject implements PDFEncryption { 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 @@ public class PDFEncryptionJCE extends PDFObject implements PDFEncryption { 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 @@ public class PDFEncryptionJCE extends PDFObject implements PDFEncryption { 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 @@ public class PDFEncryptionJCE extends PDFObject implements PDFEncryption { // 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 @@ public class PDFEncryptionJCE extends PDFObject implements PDFEncryption { 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 @@ public class PDFEncryptionJCE extends PDFObject implements PDFEncryption { 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 class PDFEncryptionJCE extends PDFObject implements PDFEncryption { */ 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 @@ public class PDFEncryptionJCE extends PDFObject implements PDFEncryption { 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 @@ public class PDFEncryptionJCE extends PDFObject implements PDFEncryption { 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 @@ public class PDFEncryptionJCE extends PDFObject implements PDFEncryption { 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 @@ public class PDFEncryptionJCE extends PDFObject implements PDFEncryption { * 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 @@ public class PDFEncryptionJCE extends PDFObject implements PDFEncryption { 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"; } } |