public byte[] decrypt(byte[] data,final String ref,final boolean isEncryption,final String cacheName,final boolean alwaysUseRC4,final boolean isString) throws PdfSecurityException {
  if (getBooleanValue(PDFflags.IS_FILE_ENCRYPTED) || isEncryption) {
    BufferedOutputStream streamCache=null;
    BufferedInputStream bis=null;
    boolean isAES=false;
    byte[] AESData=null;
    if (cacheName != null) {
      try {
        if (data == null) {
          AESData=new byte[16];
          final FileInputStream fis=new FileInputStream(cacheName);
          fis.read(AESData);
          fis.close();
        }
        final File tempFile2=File.createTempFile("jpedal",".raw",new File(ObjectStore.temp_dir));
        cachedObjects.put(tempFile2.getAbsolutePath(),"x");
        ObjectStore.copy(cacheName,tempFile2.getAbsolutePath());
        final File rawFile=new File(cacheName);
        rawFile.delete();
        streamCache=new BufferedOutputStream(new FileOutputStream(cacheName));
        bis=new BufferedInputStream(new FileInputStream(tempFile2));
      }
 catch (      final IOException e1) {
        LogWriter.writeLog("Exception " + e1 + " in decrypt");
      }
    }
    int keyLength=this.keyLength;
    String algorithm="RC4", keyType="RC4";
    IvParameterSpec ivSpec=null;
    final PdfObject AESObj;
    if (!isString) {
      AESObj=StmFObj;
    }
 else {
      AESObj=StrFObj;
    }
    if (certificate != null) {
      setPasswordFromCertificate(AESObj);
      AESObj.setIntNumber(PdfDictionary.Length,16);
    }
    if (!alwaysUseRC4 && AESObj == null && isAESIdentity) {
      return data;
    }
    if (AESObj != null) {
      final String cryptName=AESObj.getName(PdfDictionary.CFM);
      if (cryptName != null && !alwaysUseRC4 && ((cryptName.equals("AESV2") || (cryptName.equals("AESV3"))))) {
        cipher=null;
        algorithm="AES/CBC/PKCS5Padding";
        keyType="AES";
        isAES=true;
        final byte[] iv=new byte[16];
        if (AESData != null) {
          System.arraycopy(AESData,0,iv,0,16);
        }
 else {
          System.arraycopy(data,0,iv,0,16);
        }
        ivSpec=new IvParameterSpec(iv);
        if (data == null) {
          try {
            bis.skip(16);
          }
 catch (          final IOException e) {
            LogWriter.writeLog("Exception: " + e.getMessage());
          }
        }
 else {
          final int origLen=data.length;
          final int newLen=origLen - 16;
          byte[] newData=new byte[newLen];
          System.arraycopy(data,16,newData,0,newLen);
          data=newData;
          final 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;
          }
          if (rev == 5) {
            try {
              final byte[] finalKey=new byte[32];
              System.arraycopy(encryptionKey,0,finalKey,0,finalKey.length);
              return decodeAES(finalKey,data,iv);
            }
 catch (            final Exception e) {
              throw new PdfSecurityException("Exception " + e + " decrypting content in AES revision 5");
            }
          }
        }
      }
    }
    byte[] currentKey=new byte[keyLength];
    if (!ref.isEmpty()) {
      currentKey=new byte[keyLength + 5];
    }
    System.arraycopy(encryptionKey,0,currentKey,0,keyLength);
    try {
      final byte[] finalKey;
      if (rev == 5) {
        finalKey=new byte[32];
        System.arraycopy(currentKey,0,finalKey,0,finalKey.length);
      }
 else {
        if (!ref.isEmpty()) {
          final int pointer=ref.indexOf(' ');
          final int pointer2=ref.indexOf(' ',pointer + 1);
          final int obj=Integer.parseInt(ref.substring(0,pointer));
          final 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.isEmpty()) {
          final MessageDigest currentDigest=MessageDigest.getInstance("MD5");
          currentDigest.update(currentKey);
          if (isAES && keyLength >= 16) {
            final 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);
        }
      }
      if (cipher == null) {
        cipher=Cipher.getInstance(algorithm);
      }
      final 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 {
          cipher.init(Cipher.DECRYPT_MODE,testKey,ivSpec);
        }
      }
      if (streamCache != null) {
        final 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 (    final Exception e) {
      throw new PdfSecurityException("Exception " + e + " decrypting content");
    }
  }
  if (alwaysReinitCipher) {
    cipher=null;
  }
  return data;
}

public byte [ ] decrypt ( byte [ ] data , final String ref , final boolean isEncryption , final String cacheName , final boolean alwaysUseRC4 , final boolean isString ) throws PdfSecurityException { if ( getBooleanValue ( PDFflags . IS_FILE_ENCRYPTED ) || isEncryption ) { BufferedOutputStream streamCache = null ; BufferedInputStream bis = null ; boolean isAES = false ; byte [ ] AESData = null ; if ( cacheName != null ) { try { if ( data == null ) { AESData = new byte [ 16 ] ; final FileInputStream fis = new FileInputStream ( cacheName ) ; fis . read ( AESData ) ; fis . close ( ) ; } final File tempFile2 = File . createTempFile ( "jpedal" , ".raw" , new File ( ObjectStore . temp_dir ) ) ; cachedObjects . put ( tempFile2 . getAbsolutePath ( ) , "x" ) ; ObjectStore . copy ( cacheName , tempFile2 . getAbsolutePath ( ) ) ; final File rawFile = new File ( cacheName ) ; rawFile . delete ( ) ; streamCache = new BufferedOutputStream ( new FileOutputStream ( cacheName ) ) ; bis = new BufferedInputStream ( new FileInputStream ( tempFile2 ) ) ; } catch ( final IOException e1 ) { LogWriter . writeLog ( "Exception " + e1 + " in decrypt" ) ; } } int keyLength = this . keyLength ; String algorithm = "RC4" , keyType = "RC4" ; IvParameterSpec ivSpec = null ; final PdfObject AESObj ; if ( ! isString ) { AESObj = StmFObj ; } else { AESObj = StrFObj ; } if ( certificate != null ) { setPasswordFromCertificate ( AESObj ) ; AESObj . setIntNumber ( PdfDictionary . Length , 16 ) ; } if ( ! alwaysUseRC4 && AESObj == null && isAESIdentity ) { return data ; } if ( AESObj != null ) { final String cryptName = AESObj . getName ( PdfDictionary . CFM ) ; if ( cryptName != null && ! alwaysUseRC4 && ( ( cryptName . equals ( "AESV2" ) || ( cryptName . equals ( "AESV3" ) ) ) ) ) { cipher = null ; algorithm = "AES/CBC/PKCS5Padding" ; keyType = "AES" ; isAES = true ; final byte [ ] iv = new byte [ 16 ] ; if ( AESData != null ) { System . arraycopy ( AESData , 0 , iv , 0 , 16 ) ; } else { System . arraycopy ( data , 0 , iv , 0 , 16 ) ; } ivSpec = new IvParameterSpec ( iv ) ; if ( data == null ) { try { bis . skip ( 16 ) ; } catch ( final IOException e ) { LogWriter . writeLog ( "Exception: " + e . getMessage ( ) ) ; } } else { final int origLen = data . length ; final int newLen = origLen - 16 ; byte [ ] newData = new byte [ newLen ] ; System . arraycopy ( data , 16 , newData , 0 , newLen ) ; data = newData ; final 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 ; } if ( rev == 5 ) { try { final byte [ ] finalKey = new byte [ 32 ] ; System . arraycopy ( encryptionKey , 0 , finalKey , 0 , finalKey . length ) ; return decodeAES ( finalKey , data , iv ) ; } catch ( final Exception e ) { throw new PdfSecurityException ( "Exception " + e + " decrypting content in AES revision 5" ) ; } } } } } byte [ ] currentKey = new byte [ keyLength ] ; if ( ! ref . isEmpty ( ) ) { currentKey = new byte [ keyLength + 5 ] ; } System . arraycopy ( encryptionKey , 0 , currentKey , 0 , keyLength ) ; try { final byte [ ] finalKey ; if ( rev == 5 ) { finalKey = new byte [ 32 ] ; System . arraycopy ( currentKey , 0 , finalKey , 0 , finalKey . length ) ; } else { if ( ! ref . isEmpty ( ) ) { final int pointer = ref . indexOf ( ' ' ) ; final int pointer2 = ref . indexOf ( ' ' , pointer + 1 ) ; final int obj = Integer . parseInt ( ref . substring ( 0 , pointer ) ) ; final 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 . isEmpty ( ) ) { final MessageDigest currentDigest = MessageDigest . getInstance ( "MD5" ) ; currentDigest . update ( currentKey ) ; if ( isAES && keyLength >= 16 ) { final 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 ) ; } } if ( cipher == null ) { cipher = Cipher . getInstance ( algorithm ) ; } final 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 { cipher . init ( Cipher . DECRYPT_MODE , testKey , ivSpec ) ; } } if ( streamCache != null ) { final 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 ( final Exception e ) { throw new PdfSecurityException ( "Exception " + e + " decrypting content" ) ; } } if ( alwaysReinitCipher ) { cipher = null ; } return data ; }
reads the line / s from file which make up an object includes move
