/**
* ===========================================
* Java Pdf Extraction Decoding Access Library
* ===========================================
*
* Project Info: http://www.jpedal.org
* (C) Copyright 1997-2011, IDRsolutions and Contributors.
*
* This file is part of JPedal
*
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* ---------------
* DecryptionFactory.java
* ---------------
*/
package org.jpedal.io;
import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.engines.AESFastEngine;
import org.bouncycastle.crypto.modes.CBCBlockCipher;
import org.bouncycastle.crypto.params.KeyParameter;
import org.jpedal.constants.PDFflags;
import org.jpedal.exception.PdfSecurityException;
import org.jpedal.objects.raw.PdfArrayIterator;
import org.jpedal.objects.raw.PdfDictionary;
import org.jpedal.objects.raw.PdfKeyPairsIterator;
import org.jpedal.objects.raw.PdfObject;
import org.jpedal.utils.LogWriter;
import org.jpedal.utils.ObjectCloneFactory;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.security.Key;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
* Provide AES/RSA decryption support
*/
public class DecryptionFactory {
private Map cachedObjects=new HashMap();
/**flag to show if extraction allowed*/
private boolean extractionIsAllowed = true;
/**flag to show provider read*/
private boolean isInitialised=false;
private boolean isMetaDataEncypted=true;
/**flag if password supplied*/
private boolean isPasswordSupplied=false;
private boolean stringsEncoded=false;
/**flag to show data encrytped*/
private boolean isEncrypted = false;
/**key used for encryption*/
private byte[] encryptionKey=null;
/** revision used for encryption*/
private int rev=0;
/**P value in encryption*/
private int P=0;
/**O value in encryption*/
private byte[] O=null;
/**U value in encryption*/
private byte[] U=null;
/**additional 5 values*/
private byte[] OE=null, Perms=null,UE=null;
//SecOP java ME - removed to remove additional package secop1_0.jar in java ME
/**cipher used for decryption*/
Cipher cipher=null;
//show if AES encryption
private boolean isAES=false;
private PdfObject StmFObj,StrFObj;
private static boolean alwaysReinitCipher=false;
static{
String flag=System.getProperty("org.jpedal.cipher.reinit");
if(flag!=null && flag.toLowerCase().equals("true"))
alwaysReinitCipher=true;
}
/**encryption padding*/
private final String[] pad={"28","BF","4E","5E","4E","75","8A","41","64","00","4E","56","FF","FA","01","08",
"2E","2E","00","B6","D0","68","3E","80","2F","0C","A9","FE","64","53","69","7A"};
private boolean isAESIdentity=false;
/**length of encryption key used*/
private int keyLength=5;
/**flag to show if user can view file*/
private boolean isFileViewable=true;
//tell user status on password
private int passwordStatus=0;
/**holds file ID*/
private byte[] ID=null;
/**encryption password*/
private byte[] encryptionPassword = null;
private Certificate certificate;
private Key key;
public DecryptionFactory(byte[] ID, byte[] encryptionPassword){
this.ID=ID;
this.encryptionPassword=encryptionPassword;
}
/**
* version for using public certificates
* @param id
* @param certificate
* @param key
*/
public DecryptionFactory(byte[] id, Certificate certificate, PrivateKey key) {
this.ID=id;
this.certificate=certificate;
this.key=key;
}
/**see if valid for password*/
private boolean testPassword() throws PdfSecurityException {
int count=32;
byte[] rawValue=new byte[32];
byte[] keyValue ;
for(int i=0;i<32;i++)
rawValue[i]=(byte)Integer.parseInt(pad[i],16);
byte[] encrypted= ObjectCloneFactory.cloneArray(rawValue);
if (rev==2) {
encryptionKey=calculateKey(O,P,ID);
encrypted=decrypt(encrypted,"", true,null,false,false);
} else if(rev>=3) {
//use StmF values in preference
int keyLength=this.keyLength;
if(rev==4 && StmFObj!=null){
int lenKey=StmFObj.getInt(PdfDictionary.Length);
if(lenKey!=-1)
keyLength=lenKey;
}
count=16;
encryptionKey=calculateKey(O,P,ID);
byte[] originalKey= ObjectCloneFactory.cloneArray(encryptionKey);
MessageDigest md = null;
try {
md = MessageDigest.getInstance("MD5");
} catch (Exception e) {
if(LogWriter.isOutput())
LogWriter.writeLog("Exception " + e + " with digest");
}
md.update(encrypted);
//feed in ID
keyValue = md.digest(ID);
keyValue=decrypt(keyValue,"", true,null,true,false);
byte[] nextKey = new byte[keyLength];
for (int i=1; i<=19; i++) {
for (int j=0; j<keyLength; j++)
nextKey[j] = (byte)(originalKey[j] ^ i);
encryptionKey=nextKey;
keyValue=decrypt(keyValue,"", true,null,true,false);
}
encryptionKey=originalKey;
encrypted = new byte[32];
System.arraycopy(keyValue,0, encrypted,0, 16);
System.arraycopy(rawValue,0, encrypted,16, 16);
}
return compareKeys(U, encrypted,count);
}
private static boolean compareKeys(byte[] U, byte[] encrypted, int count) {
boolean match=true;
for(int i=0;i<count;i++){
if(U[i]!=encrypted[i]){
match =false;
i=U.length;
}
}
return match;
}
/**set the key value*/
private void computeEncryptionKey() throws PdfSecurityException{
MessageDigest md;
/**calculate key to use*/
byte[] key=getPaddedKey(encryptionPassword);
/**feed into Md5 function*/
try{
// Obtain a message digest object.
md = MessageDigest.getInstance("MD5");
encryptionKey=md.digest(key);
/**rev 3 extra security*/
if(rev>=3){
for (int ii=0; ii<50; ii++)
encryptionKey = md.digest(encryptionKey);
}
}catch(Exception e){
throw new PdfSecurityException("Exception "+e+" generating encryption key");
}
}
/**see if valid for password*/
private boolean testOwnerPassword() throws PdfSecurityException{
byte[] originalPassword=encryptionPassword;
byte[] userPasswd=new byte[keyLength];
byte[] inputValue= ObjectCloneFactory.cloneArray(O);
computeEncryptionKey();
byte[] originalKey= ObjectCloneFactory.cloneArray(encryptionKey);
if(rev==2){
userPasswd=decrypt(ObjectCloneFactory.cloneArray(O),"", false,null,false,false);
}else if(rev>=3){
//use StmF values in preference
int keyLength=this.keyLength;
if(rev==4 && StmFObj!=null){
int lenKey=StmFObj.getInt(PdfDictionary.Length);
if(lenKey!=-1)
keyLength=lenKey;
}
userPasswd=inputValue;
byte[] nextKey = new byte[keyLength];
for (int i=19; i>=0; i--) {
for (int j=0; j<keyLength; j++)
nextKey[j] = (byte)(originalKey[j] ^ i);
encryptionKey=nextKey;
userPasswd=decrypt(userPasswd,"", false,null,true,false);
}
}
//this value is the user password if correct
//so test
encryptionPassword = userPasswd;
computeEncryptionKey();
boolean isMatch=testPassword();
//put back to original if not in fact correct
if(!isMatch){
encryptionPassword=originalPassword;
computeEncryptionKey();
}
return isMatch;
}
/**test password and set access settings*/
private void verifyAccess() throws PdfSecurityException{
/**assume false*/
isPasswordSupplied=false;
extractionIsAllowed=false;
passwordStatus= PDFflags.NO_VALID_PASSWORD;
/**workout if user or owner password valid*/
boolean isOwnerPassword=false,isUserPassword=false;
if(rev<5){
isOwnerPassword =testOwnerPassword();
isUserPassword=testPassword();
}else{ //v5 method very different so own routines to handle
try {
isOwnerPassword=compareKeys(O,getV5Key(true,32),32);
if(isOwnerPassword){
encryptionKey= v5Decrypt(OE, getV5Key(true, 32));
}else{ //try user
isUserPassword=compareKeys(U, getV5Key(false,32),32);
if(isUserPassword) //if not set throws error below
encryptionKey= v5Decrypt(UE, getV5Key(false, 40));
}
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
if(isOwnerPassword)
passwordStatus=PDFflags.VALID_OWNER_PASSWORD;
if(isUserPassword)
passwordStatus=passwordStatus+PDFflags.VALID_USER_PASSWORD;
if(!isOwnerPassword){
/**test if user first*/
if(isUserPassword){
//tell if not default value
if(encryptionPassword!=null && encryptionPassword.length>0 && LogWriter.isOutput())
LogWriter.writeLog("Correct user password supplied ");
isFileViewable=true;
isPasswordSupplied=true;
if((P & 16)==16)
extractionIsAllowed=true;
}else
throw new PdfSecurityException("No valid password supplied");
}else{
if(LogWriter.isOutput())
LogWriter.writeLog("Correct owner password supplied");
isFileViewable=true;
isPasswordSupplied=true;
extractionIsAllowed=true;
}
}
/**
* workout key from OE or UE
*/
private static byte[] v5Decrypt(byte[] rawValue, byte[] key) throws PdfSecurityException {
int ELength= rawValue.length;
byte[] returnKey = new byte[ELength];
try{
//setup Cipher
BlockCipher cbc = new CBCBlockCipher(new AESFastEngine());
cbc.init(false, new KeyParameter(key));
//translate bytes
int nextBlockSize;
for(int i=0;i<ELength;i=i+nextBlockSize){
cbc.processBlock(rawValue, i, returnKey, i);
nextBlockSize=cbc.getBlockSize();
}
}catch(Exception e){
throw new PdfSecurityException("Exception "+e.getMessage()+" with v5 encoding");
}
return returnKey;
}
private byte[] getV5Key(boolean isOwner, int offset) throws NoSuchAlgorithmException {
//set password and ensure not null
byte[] password=this.encryptionPassword;
if(password==null)
password=new byte[0];
//ignore anything over 128
int passwordLength=password.length;
if(passwordLength>127)
passwordLength=127;
/**
* feed in values
*/
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(password, 0, passwordLength);
if(isOwner){
md.update(O, offset, 8);
md.update(U, 0, 48);
}else
md.update(U, offset, 8);
return md.digest();
}
/**
* routine to create a padded key
*/
private byte[] getPaddedKey(byte[] password){
/**get 32 bytes for the key*/
byte[] key=new byte[32];
int passwordLength=0;
if(password!=null){
passwordLength=password.length;
if(passwordLength>32)
passwordLength=32;
}
if(encryptionPassword!=null)
System.arraycopy(encryptionPassword, 0, key, 0, passwordLength);
for(int ii=passwordLength;ii<32;ii++){
key[ii]=(byte)Integer.parseInt(pad[ii-passwordLength],16);
}
return key;
}
/**
* calculate the key
*/
private byte[] calculateKey(byte[] O,int P,byte[] ID) throws PdfSecurityException{
/**calculate key to use*/
byte[] key=getPaddedKey(encryptionPassword),keyValue;
/**feed into Md5 function*/
try{
// Obtain a message digest object.
MessageDigest md = MessageDigest.getInstance("MD5");
//add in padded key
md.update(key);
//write in O value
md.update(O);
//P value
md.update(new byte[]{(byte)((P) & 0xff),(byte)((P>>8) & 0xff),(byte)((P>>16) & 0xff),(byte)((P>>24) & 0xff)});
if(ID!=null)
md.update(ID);
if (rev==4 && !isMetaDataEncypted)
md.update(new byte[]{(byte)255,(byte)255,(byte)255,(byte)255});
byte digest[] = new byte[keyLength];
System.arraycopy(md.digest(), 0, digest, 0, keyLength);
//for rev 3
if(rev>=3){
for (int i = 0; i < 50; ++i)
System.arraycopy(md.digest(digest), 0, digest, 0, keyLength);
}
keyValue=new byte[keyLength];
System.arraycopy(digest, 0, keyValue, 0, keyLength);
}catch(Exception e){
e.printStackTrace();
throw new PdfSecurityException("Exception "+e+" generating encryption key");
}
/**put significant bytes into key*/
byte[] returnKey = new byte[keyLength];
System.arraycopy(keyValue,0, returnKey,0, keyLength);
return returnKey;
}
/**extract metadata for encryption object
*/
public void readEncryptionObject(PdfObject encyptionObj) throws PdfSecurityException {
//reset flags
stringsEncoded=false;
isMetaDataEncypted=true;
StmFObj=null;
StrFObj=null;
isAES=false;
if (!isInitialised) {
isInitialised = true;
SetSecurity.init();
}
//check type of filter and type and see if supported
int v = encyptionObj.getInt(PdfDictionary.V);
//get filter value
PdfArrayIterator filters = encyptionObj.getMixedArray(PdfDictionary.Filter);
int firstValue=PdfDictionary.Standard;
if(filters!=null && filters.hasMoreTokens())
firstValue=filters.getNextValueAsConstant(false);
//throw exception if we have an unsupported encryption method
if(v==3)
throw new PdfSecurityException("Unsupported Custom Adobe Encryption method");
else if (v > 4){
if(firstValue!=PdfDictionary.Standard)
throw new PdfSecurityException("Unsupported Encryption method");
}
int newLength=encyptionObj.getInt(PdfDictionary.Length)>>3;
if(newLength!=-1)
this.keyLength=newLength;
//get rest of the values (which are not optional)
rev = encyptionObj.getInt(PdfDictionary.R);
P = encyptionObj.getInt(PdfDictionary.P);
O = encyptionObj.getTextStreamValueAsByte(PdfDictionary.O);
U = encyptionObj.getTextStreamValueAsByte(PdfDictionary.U);
//used for v=5
OE = encyptionObj.getTextStreamValueAsByte(PdfDictionary.OE);
UE = encyptionObj.getTextStreamValueAsByte(PdfDictionary.UE);
Perms=encyptionObj.getTextStreamValueAsByte(PdfDictionary.Perms);
//get additional AES values
if(v>=4){
isAES=true;
String CFkey;
PdfObject CF=encyptionObj.getDictionary(PdfDictionary.CF);
//EFF=encyptionObj.getName(PdfDictionary.EFF);
//CFM=encyptionObj.getName(PdfDictionary.CFM);
if(v==4){
isMetaDataEncypted=encyptionObj.getBoolean(PdfDictionary.EncryptMetadata);
}
//now set any specific crypt values for StrF (strings) and StmF (streams)
isAESIdentity=false;
String key=encyptionObj.getName(PdfDictionary.StrF);
if(key!=null){
isAESIdentity=key.equals("Identity");
stringsEncoded=true;
PdfKeyPairsIterator keyPairs=CF.getKeyPairsIterator();
while(keyPairs.hasMorePairs()){
CFkey=keyPairs.getNextKeyAsString();
if(CFkey.equals(key))
StrFObj=keyPairs.getNextValueAsDictionary();
//roll on
keyPairs.nextPair();
}
}
key=encyptionObj.getName(PdfDictionary.StmF);
if(key!=null){
isAESIdentity=key.equals("Identity");
PdfKeyPairsIterator keyPairs=CF.getKeyPairsIterator();
while(keyPairs.hasMorePairs()){
CFkey=keyPairs.getNextKeyAsString();
if(CFkey.equals(key))
StmFObj=keyPairs.getNextValueAsDictionary();
//roll on
keyPairs.nextPair();
}
}
}
isEncrypted = true;
isFileViewable = false;
if(LogWriter.isOutput())
LogWriter.writeLog("File has encryption settings");
//test if encrypted with password (not certificate)
if(firstValue==PdfDictionary.Standard){
try{
verifyAccess();
}catch(PdfSecurityException e){
if(LogWriter.isOutput())
LogWriter.writeLog("File requires password");
}
}else if(certificate!=null){
/**
* set flags and assume it will work correctly
* (no validation at this point - error will be thrown in decrypt if not)
*/
isFileViewable=true;
isPasswordSupplied=true;
extractionIsAllowed=true;
passwordStatus=PDFflags.VALID_OWNER_PASSWORD;
}
//v5 stores this in Perms object and needs to be done after verify access
if(rev==5){
/*
* now decode the permissions
*/
Perms= v5Decrypt(Perms, encryptionKey);
//see if metadata encrypted
isMetaDataEncypted = Perms[8] == 'T';
//P set in Perms for v5
P = (Perms[0] & 255) | ((Perms[1] & 255) << 8) | ((Perms[2] & 255) << 16) | ((Perms[2] & 255) << 24);
}
}
/**
* setup password value isung certificate passed in by User
*/
private void setPasswordFromCertificate(PdfObject AESObj){
/**
* if recipients set, use that for calculating key
*/
byte[][] recipients = (AESObj.getStringArray(PdfDictionary.Recipients));
if(recipients!=null){
byte[] envelopedData=SetSecurity.extractCertificateData(recipients,certificate,key);
/**
* use match to create the key
*/
if(envelopedData!=null){
try {
MessageDigest md = MessageDigest.getInstance("SHA-1");
md.update(envelopedData, 0, 20);
for (byte[] recipient : recipients) {
md.update(recipient);
}
if (!isMetaDataEncypted)
md.update(new byte[]{(byte)255, (byte)255, (byte)255, (byte)255});
encryptionKey = md.digest();
}catch (Exception ee) {
ee.printStackTrace();
}
}
}
}
/**
* reads the line/s from file which make up an object
* includes move
*/
public byte[] decrypt(byte[] data, String ref,boolean isEncryption,
String cacheName,boolean alwaysUseRC4,
boolean isString) throws PdfSecurityException{
//boolean debug=false;//ref.equals("100 0 R");
if(getBooleanValue(PDFflags.IS_FILE_ENCRYPTED) || isEncryption){
BufferedOutputStream streamCache= null;
BufferedInputStream bis = null;
//int streamLength=0;
boolean isAES=false;
byte[] AESData=null;
if(cacheName!=null){ //this version is used if we cache large object to disk
//rename file
try {
//we may need bytes for key
if(data==null){
AESData=new byte[16];
FileInputStream fis=new FileInputStream(cacheName);
fis.read(AESData);
fis.close();
}
//streamLength = (int) new File(cacheName).length();
File tempFile2 = File.createTempFile("jpedal",".raw",new File(ObjectStore.temp_dir));
cachedObjects.put(tempFile2.getAbsolutePath(),"x");
//System.out.println(">>>"+tempFile2.getAbsolutePath());
ObjectStore.copy(cacheName,tempFile2.getAbsolutePath());
File rawFile=new File(cacheName);
rawFile.delete();
//decrypt
streamCache = new BufferedOutputStream(new FileOutputStream(cacheName));
bis=new BufferedInputStream(new FileInputStream(tempFile2));
} catch (IOException e1) {
if(LogWriter.isOutput())
LogWriter.writeLog("Exception "+e1+" in decrypt");
}
}
//default values for rsa
int keyLength=this.keyLength;
String algorithm="RC4",keyType="RC4";
//SecOP java ME - removed to remove additional package secop1_0.jar in java ME
IvParameterSpec ivSpec = null;
//select for stream or string
PdfObject AESObj ;
if(!isString){
AESObj=StmFObj;
}else{
AESObj=StrFObj;
}
/**
* reset each time as can change
* (we can add flag later if slow)
*/
if(certificate!=null){
setPasswordFromCertificate(AESObj);
//ensure value set so code below works
AESObj.setIntNumber(PdfDictionary.Length,16);
}
//AES identity
if(!alwaysUseRC4 && AESObj==null && isAESIdentity)
return data;
//use RC4 as default but override if needed
if(AESObj!=null){
//use CF values in preference
int AESLength=AESObj.getInt(PdfDictionary.Length);
if(AESLength!=-1)
keyLength=AESLength;
String cryptName=AESObj.getName(PdfDictionary.CFM);
if(cryptName!=null && !alwaysUseRC4 && ((cryptName.equals("AESV2")|| (cryptName.equals("AESV3"))))){
cipher=null; //force reset as may be rsa
algorithm="AES/CBC/PKCS5Padding";
keyType="AES";
isAES=true;
//setup CBC
byte[] iv=new byte[16];
if(AESData!=null)
System.arraycopy(AESData, 0, iv, 0, 16);
else
System.arraycopy(data, 0, iv, 0, 16);
//SecOP java ME - removed to remove additional package secop1_0.jar in java ME
ivSpec = new IvParameterSpec(iv);
//and knock off iv data in memory or cache
if(data==null){
try {
bis.skip(16);
} catch (IOException e) {
e.printStackTrace();
}
}else{
int origLen=data.length;
int newLen=origLen-16;
byte[] newData=new byte[newLen];
System.arraycopy(data, 16, newData, 0, newLen);
data=newData;
//make sure data correct size
int diff= (data.length & 15);
int newLength=data.length;
if(diff>0){
newLength=newLength+16-diff;
newData=new byte[newLength];
System.arraycopy(data, 0, newData, 0, data.length);
data=newData;
}
}
}
}
byte[] currentKey=new byte[keyLength];
if(ref.length()>0)
currentKey=new byte[keyLength+5];
System.arraycopy(encryptionKey, 0, currentKey, 0, keyLength);
try{
byte[] finalKey;
if(rev==5){
finalKey=new byte[32];
System.arraycopy(currentKey,0, finalKey,0, finalKey.length);
// finalKey=currentKey;
}else{
//add in Object ref id if any
if(ref.length()>0){
int pointer=ref.indexOf(' ');
int pointer2=ref.indexOf(' ',pointer+1);
int obj=Integer.parseInt(ref.substring(0,pointer));
int gen=Integer.parseInt(ref.substring(pointer+1,pointer2));
currentKey[keyLength]=((byte)(obj & 0xff));
currentKey[keyLength+1]=((byte)((obj>>8) & 0xff));
currentKey[keyLength+2]=((byte)((obj>>16) & 0xff));
currentKey[keyLength+3]=((byte)(gen & 0xff));
currentKey[keyLength+4]=((byte)((gen>>8) & 0xff));
}
finalKey = new byte[Math.min(currentKey.length,16)];
if(ref.length()>0){
MessageDigest currentDigest =MessageDigest.getInstance("MD5");
currentDigest.update(currentKey);
//add in salt
if(isAES && keyLength>=16){
byte[] salt = {(byte)0x73, (byte)0x41, (byte)0x6c, (byte)0x54};
currentDigest.update(salt);
}
System.arraycopy(currentDigest.digest(),0, finalKey,0, finalKey.length);
}else{
System.arraycopy(currentKey,0, finalKey,0, finalKey.length);
}
}
//SecOP java ME - removed to remove additional package secop1_0.jar in java ME
/**only initialise once - seems to take a long time*/
if(cipher==null)
cipher = Cipher.getInstance(algorithm);
SecretKey testKey = new SecretKeySpec(finalKey, keyType);
if(isEncryption)
cipher.init(Cipher.ENCRYPT_MODE, testKey);
else{
if(ivSpec==null)
cipher.init(Cipher.DECRYPT_MODE, testKey);
else //aes
cipher.init(Cipher.DECRYPT_MODE, testKey,ivSpec);
}
//if data on disk read a byte at a time and write back
if(streamCache!=null){
CipherInputStream cis=new CipherInputStream(bis,cipher);
int nextByte;
while(true){
nextByte=cis.read();
if(nextByte==-1)
break;
streamCache.write(nextByte);
}
cis.close();
streamCache.close();
bis.close();
}
if(data!=null)
data=cipher.doFinal(data);
}catch(Exception e){
throw new PdfSecurityException("Exception "+e+" decrypting content");
}
}
//SecOP java ME - removed to remove additional package secop1_0.jar in java ME
if(alwaysReinitCipher)
cipher=null;
return data;
}
/**show if file can be displayed*/
public boolean getBooleanValue(int key) {
switch(key){
case PDFflags.IS_FILE_VIEWABLE:
return isFileViewable;
case PDFflags.IS_FILE_ENCRYPTED:
return isEncrypted;
case PDFflags.IS_METADATA_ENCRYPTED:
return isMetaDataEncypted;
case PDFflags.IS_EXTRACTION_ALLOWED:
return extractionIsAllowed;
case PDFflags.IS_PASSWORD_SUPPLIED:
return isPasswordSupplied;
}
return false;
}
public byte[] decryptString(byte[] newString, String objectRef) throws PdfSecurityException {
try{
if((!isAES || stringsEncoded || isMetaDataEncypted))
newString=decrypt(newString, objectRef, false, null, false, true);
}catch(Exception e){
if(LogWriter.isOutput())
LogWriter.writeLog("Unable to decrypt string in Object "+objectRef+ ' ' +new String(newString));
}
return newString;
}
public int getPDFflag(Integer flag) {
if(flag.equals(PDFflags.USER_ACCESS_PERMISSIONS))
return P;
else if(flag.equals(PDFflags.VALID_PASSWORD_SUPPLIED))
return passwordStatus;
else
return -1;
}
public void reset(byte[] encryptionPassword) {
this.encryptionPassword=encryptionPassword;
//SecOP java ME - removed to remove additional package secop1_0.jar in java ME
//reset
cipher=null;
}
public void flush() {
if(cachedObjects!=null){
for (Object o : cachedObjects.keySet()) {
String fileName = (String) o;
File file = new File(fileName);
//System.out.println("PdfFileReader - deleting file "+fileName);
file.delete();
if (LogWriter.isOutput() && file.exists())
LogWriter.writeLog("Unable to delete temp file " + fileName);
}
}
}
public void dispose() {
this.cachedObjects=null;
}
/**
* show if U or O value present
* @return
*/
public boolean hasPassword() {
return O!=null || U!=null;
}
}