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;
this.encryption = encryption;
this.number = number;
this.generation = generation;
+ //System.out.println("new encryption filter for number "
+ // +number+" and generation "+generation);
}
/**
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 =
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;
// Encryption tools
private MessageDigest digest = null;
- private Cipher cipher = null;
+ //private Cipher cipher = null;
private Random random = new Random();
// Control attributes
private PDFEncryptionParams params;
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());*/
}
}
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
*/
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;
}
/**
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";
}
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++;
}
hash[i++] = (byte) (number >>> 16);
hash[i++] = (byte) (generation >>> 0);
hash[i++] = (byte) (generation >>> 8);;
-
- return encryptWithHash(data, hash, hash.length);
+ return hash;
}
/**
* 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()));
}
/**
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";
}
}