You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by ki...@apache.org on 2016/09/28 23:36:09 UTC

svn commit: r1762726 [3/3] - in /poi: site/src/documentation/content/xdocs/ trunk/ trunk/src/java/org/apache/poi/ trunk/src/java/org/apache/poi/hssf/model/ trunk/src/java/org/apache/poi/hssf/record/ trunk/src/java/org/apache/poi/hssf/record/cont/ trunk...

Modified: poi/trunk/src/java/org/apache/poi/util/LittleEndianInput.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/util/LittleEndianInput.java?rev=1762726&r1=1762725&r2=1762726&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/util/LittleEndianInput.java (original)
+++ poi/trunk/src/java/org/apache/poi/util/LittleEndianInput.java Wed Sep 28 23:36:09 2016
@@ -16,10 +16,7 @@
 ==================================================================== */
 
 package org.apache.poi.util;
-/**
- *
- * @author Josh Micich
- */
+
 public interface LittleEndianInput {
 	int available();
 	byte readByte();
@@ -31,4 +28,14 @@ public interface LittleEndianInput {
 	double readDouble();
 	void readFully(byte[] buf);
 	void readFully(byte[] buf, int off, int len);
+
+	/**
+	 * Usually acts the same as {@link #readFully(byte[], int, int)}, but
+	 * for an encrypted stream the raw (unencrypted) data is filled 
+	 *
+	 * @param buf the byte array to receive the bytes
+	 * @param off the start offset into the byte array 
+	 * @param len the amount of bytes to fill
+	 */
+	void readPlain(byte[] buf, int off, int len);
 }

Modified: poi/trunk/src/java/org/apache/poi/util/LittleEndianInputStream.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/util/LittleEndianInputStream.java?rev=1762726&r1=1762725&r2=1762726&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/util/LittleEndianInputStream.java (original)
+++ poi/trunk/src/java/org/apache/poi/util/LittleEndianInputStream.java Wed Sep 28 23:36:09 2016
@@ -34,7 +34,8 @@ public class LittleEndianInputStream ext
 		super(is);
 	}
 	
-	public int available() {
+	@Override
+    public int available() {
 		try {
 			return super.available();
 		} catch (IOException e) {
@@ -42,11 +43,13 @@ public class LittleEndianInputStream ext
 		}
 	}
 	
-	public byte readByte() {
+	@Override
+    public byte readByte() {
 		return (byte)readUByte();
 	}
 	
-	public int readUByte() {
+	@Override
+    public int readUByte() {
 		byte buf[] = new byte[1];
 		try {
 			checkEOF(read(buf), 1);
@@ -56,11 +59,13 @@ public class LittleEndianInputStream ext
 		return LittleEndian.getUByte(buf);
 	}
 	
-	public double readDouble() {
+	@Override
+    public double readDouble() {
 		return Double.longBitsToDouble(readLong());
 	}
 	
-	public int readInt() {
+	@Override
+    public int readInt() {
 	    byte buf[] = new byte[LittleEndianConsts.INT_SIZE];
 		try {
 		    checkEOF(read(buf), buf.length);
@@ -82,7 +87,8 @@ public class LittleEndianInputStream ext
        return retNum & 0x00FFFFFFFFL;
     }
 	
-	public long readLong() {
+	@Override
+    public long readLong() {
 		byte buf[] = new byte[LittleEndianConsts.LONG_SIZE];
 		try {
 		    checkEOF(read(buf), LittleEndianConsts.LONG_SIZE);
@@ -92,11 +98,13 @@ public class LittleEndianInputStream ext
 		return LittleEndian.getLong(buf);
 	}
 	
-	public short readShort() {
+	@Override
+    public short readShort() {
 		return (short)readUShort();
 	}
 	
-	public int readUShort() {
+	@Override
+    public int readUShort() {
 		byte buf[] = new byte[LittleEndianConsts.SHORT_SIZE];
 		try {
 		    checkEOF(read(buf), LittleEndianConsts.SHORT_SIZE);
@@ -112,15 +120,22 @@ public class LittleEndianInputStream ext
 		}
 	}
 
-	public void readFully(byte[] buf) {
+	@Override
+    public void readFully(byte[] buf) {
 		readFully(buf, 0, buf.length);
 	}
 
-	public void readFully(byte[] buf, int off, int len) {
+	@Override
+    public void readFully(byte[] buf, int off, int len) {
 	    try {
 	        checkEOF(read(buf, off, len), len);
 	    } catch (IOException e) {
             throw new RuntimeException(e);
         }
 	}
+
+    @Override
+    public void readPlain(byte[] buf, int off, int len) {
+        readFully(buf, off, len);
+    }
 }

Modified: poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileDecryptor.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileDecryptor.java?rev=1762726&r1=1762725&r2=1762726&view=diff
==============================================================================
--- poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileDecryptor.java (original)
+++ poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileDecryptor.java Wed Sep 28 23:36:09 2016
@@ -45,7 +45,7 @@ import org.apache.poi.poifs.crypt.Cipher
 import org.apache.poi.poifs.crypt.CryptoFunctions;
 import org.apache.poi.poifs.crypt.Decryptor;
 import org.apache.poi.poifs.crypt.EncryptionHeader;
-import org.apache.poi.poifs.crypt.EncryptionInfoBuilder;
+import org.apache.poi.poifs.crypt.EncryptionInfo;
 import org.apache.poi.poifs.crypt.EncryptionVerifier;
 import org.apache.poi.poifs.crypt.HashAlgorithm;
 import org.apache.poi.poifs.crypt.agile.AgileEncryptionVerifier.AgileCertificateEntry;
@@ -56,14 +56,14 @@ import org.apache.poi.util.LittleEndian;
 /**
  * Decryptor implementation for Agile Encryption
  */
-public class AgileDecryptor extends Decryptor {
+public class AgileDecryptor extends Decryptor implements Cloneable {
     private long _length = -1;
 
-    protected static final byte[] kVerifierInputBlock;
-    protected static final byte[] kHashedVerifierBlock;
-    protected static final byte[] kCryptoKeyBlock;
-    protected static final byte[] kIntegrityKeyBlock;
-    protected static final byte[] kIntegrityValueBlock;
+    /* package */ static final byte[] kVerifierInputBlock;
+    /* package */ static final byte[] kHashedVerifierBlock;
+    /* package */ static final byte[] kCryptoKeyBlock;
+    /* package */ static final byte[] kIntegrityKeyBlock;
+    /* package */ static final byte[] kIntegrityValueBlock;
 
     static {
         kVerifierInputBlock =
@@ -83,16 +83,16 @@ public class AgileDecryptor extends Decr
                          (byte)0xb2, (byte)0x2c, (byte)0x84, (byte)0x33 };
     }
 
-    protected AgileDecryptor(AgileEncryptionInfoBuilder builder) {
-        super(builder);
+    protected AgileDecryptor() {
     }
     
     /**
      * set decryption password
      */
+    @Override
     public boolean verifyPassword(String password) throws GeneralSecurityException {
-        AgileEncryptionVerifier ver = (AgileEncryptionVerifier)builder.getVerifier();
-        AgileEncryptionHeader header = (AgileEncryptionHeader)builder.getHeader(); 
+        AgileEncryptionVerifier ver = (AgileEncryptionVerifier)getEncryptionInfo().getVerifier();
+        AgileEncryptionHeader header = (AgileEncryptionHeader)getEncryptionInfo().getHeader(); 
         HashAlgorithm hashAlgo = header.getHashAlgorithmEx();
         CipherAlgorithm cipherAlgo = header.getCipherAlgorithm();
         int blockSize = header.getBlockSize();
@@ -113,7 +113,7 @@ public class AgileDecryptor extends Decr
          *    blockSize bytes.
          * 4. Use base64 to encode the result of step 3.
          */
-        byte verfierInputEnc[] = hashInput(builder, pwHash, kVerifierInputBlock, ver.getEncryptedVerifier(), Cipher.DECRYPT_MODE);
+        byte verfierInputEnc[] = hashInput(getEncryptionInfo(), pwHash, kVerifierInputBlock, ver.getEncryptedVerifier(), Cipher.DECRYPT_MODE);
         setVerifier(verfierInputEnc);
         MessageDigest hashMD = getMessageDigest(hashAlgo);
         byte[] verifierHash = hashMD.digest(verfierInputEnc);
@@ -130,7 +130,7 @@ public class AgileDecryptor extends Decr
          *    blockSize bytes, pad the hash value with 0x00 to an integral multiple of blockSize bytes.
          * 4. Use base64 to encode the result of step 3.
          */
-        byte verifierHashDec[] = hashInput(builder, pwHash, kHashedVerifierBlock, ver.getEncryptedVerifierHash(), Cipher.DECRYPT_MODE);
+        byte verifierHashDec[] = hashInput(getEncryptionInfo(), pwHash, kHashedVerifierBlock, ver.getEncryptedVerifierHash(), Cipher.DECRYPT_MODE);
         verifierHashDec = getBlock0(verifierHashDec, hashAlgo.hashSize);
         
         /**
@@ -146,7 +146,7 @@ public class AgileDecryptor extends Decr
          *    blockSize bytes.
          * 4. Use base64 to encode the result of step 3.
          */
-        byte keyspec[] = hashInput(builder, pwHash, kCryptoKeyBlock, ver.getEncryptedKey(), Cipher.DECRYPT_MODE);
+        byte keyspec[] = hashInput(getEncryptionInfo(), pwHash, kCryptoKeyBlock, ver.getEncryptedKey(), Cipher.DECRYPT_MODE);
         keyspec = getBlock0(keyspec, keySize);
         SecretKeySpec secretKey = new SecretKeySpec(keyspec, ver.getCipherAlgorithm().jceId);
 
@@ -204,8 +204,8 @@ public class AgileDecryptor extends Decr
      * @throws GeneralSecurityException
      */
     public boolean verifyPassword(KeyPair keyPair, X509Certificate x509) throws GeneralSecurityException {
-        AgileEncryptionVerifier ver = (AgileEncryptionVerifier)builder.getVerifier();
-        AgileEncryptionHeader header = (AgileEncryptionHeader)builder.getHeader();
+        AgileEncryptionVerifier ver = (AgileEncryptionVerifier)getEncryptionInfo().getVerifier();
+        AgileEncryptionHeader header = (AgileEncryptionHeader)getEncryptionInfo().getHeader();
         HashAlgorithm hashAlgo = header.getHashAlgorithmEx();
         CipherAlgorithm cipherAlgo = header.getCipherAlgorithm();
         int blockSize = header.getBlockSize();
@@ -217,7 +217,9 @@ public class AgileDecryptor extends Decr
                 break;
             }
         }
-        if (ace == null) return false;
+        if (ace == null) {
+            return false;
+        }
         
         Cipher cipher = Cipher.getInstance("RSA");
         cipher.init(Cipher.DECRYPT_MODE, keyPair.getPrivate());
@@ -255,9 +257,9 @@ public class AgileDecryptor extends Decr
         return fillSize;
     }
 
-    protected static byte[] hashInput(EncryptionInfoBuilder builder, byte pwHash[], byte blockKey[], byte inputKey[], int cipherMode) {
-        EncryptionVerifier ver = builder.getVerifier();
-        AgileDecryptor dec = (AgileDecryptor)builder.getDecryptor();
+    protected static byte[] hashInput(EncryptionInfo encryptionInfo, byte pwHash[], byte blockKey[], byte inputKey[], int cipherMode) {
+        EncryptionVerifier ver = encryptionInfo.getVerifier();
+        AgileDecryptor dec = (AgileDecryptor)encryptionInfo.getDecryptor();
         int keySize = dec.getKeySizeInBytes();
         int blockSize = dec.getBlockSizeInBytes();
         HashAlgorithm hashAlgo = ver.getHashAlgorithm();
@@ -278,6 +280,7 @@ public class AgileDecryptor extends Decr
         }
     }
 
+    @Override
     @SuppressWarnings("resource")
     public InputStream getDataStream(DirectoryNode dir) throws IOException, GeneralSecurityException {
         DocumentInputStream dis = dir.createDocumentInputStream(DEFAULT_POIFS_ENTRY);
@@ -285,17 +288,20 @@ public class AgileDecryptor extends Decr
         return new AgileCipherInputStream(dis, _length);
     }
 
+    @Override
     public long getLength(){
-        if(_length == -1) throw new IllegalStateException("EcmaDecryptor.getDataStream() was not called");
+        if(_length == -1) {
+            throw new IllegalStateException("EcmaDecryptor.getDataStream() was not called");
+        }
         return _length;
     }
 
 
-    protected static Cipher initCipherForBlock(Cipher existing, int block, boolean lastChunk, EncryptionInfoBuilder builder, SecretKey skey, int encryptionMode)
+    protected static Cipher initCipherForBlock(Cipher existing, int block, boolean lastChunk, EncryptionInfo encryptionInfo, SecretKey skey, int encryptionMode)
     throws GeneralSecurityException {
-        EncryptionHeader header = builder.getHeader();
-        if (existing == null || lastChunk) {
-            String padding = (lastChunk ? "PKCS5Padding" : "NoPadding");
+        EncryptionHeader header = encryptionInfo.getHeader();
+        String padding = (lastChunk ? "PKCS5Padding" : "NoPadding");
+        if (existing == null || !existing.getAlgorithm().endsWith(padding)) {
             existing = getCipher(skey, header.getCipherAlgorithm(), header.getChainingMode(), header.getKeySalt(), encryptionMode, padding);
         }
 
@@ -339,9 +345,15 @@ public class AgileDecryptor extends Decr
         // TODO: calculate integrity hmac while reading the stream
         // for a post-validation of the data
         
+        @Override
         protected Cipher initCipherForBlock(Cipher cipher, int block)
         throws GeneralSecurityException {
-            return AgileDecryptor.initCipherForBlock(cipher, block, false, builder, getSecretKey(), Cipher.DECRYPT_MODE);
+            return AgileDecryptor.initCipherForBlock(cipher, block, false, getEncryptionInfo(), getSecretKey(), Cipher.DECRYPT_MODE);
         }
     }
+    
+    @Override
+    public AgileDecryptor clone() throws CloneNotSupportedException {
+        return (AgileDecryptor)super.clone();
+    }
 }

Modified: poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptionHeader.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptionHeader.java?rev=1762726&r1=1762725&r2=1762726&view=diff
==============================================================================
--- poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptionHeader.java (original)
+++ poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptionHeader.java Wed Sep 28 23:36:09 2016
@@ -27,7 +27,7 @@ import com.microsoft.schemas.office.x200
 import com.microsoft.schemas.office.x2006.encryption.EncryptionDocument;
 import com.microsoft.schemas.office.x2006.encryption.STCipherChaining;
 
-public class AgileEncryptionHeader extends EncryptionHeader {
+public class AgileEncryptionHeader extends EncryptionHeader implements Cloneable {
     private byte encryptedHmacKey[], encryptedHmacValue[];
     
     public AgileEncryptionHeader(String descriptor) {
@@ -99,6 +99,7 @@ public class AgileEncryptionHeader exten
     }
 
     // make method visible for this package
+    @Override
     protected void setKeySalt(byte salt[]) {
         if (salt == null || salt.length != getBlockSize()) {
             throw new EncryptedDocumentException("invalid verifier salt");
@@ -121,4 +122,13 @@ public class AgileEncryptionHeader exten
     protected void setEncryptedHmacValue(byte[] encryptedHmacValue) {
         this.encryptedHmacValue = (encryptedHmacValue == null) ? null : encryptedHmacValue.clone();
     }
+
+    @Override
+    public AgileEncryptionHeader clone() throws CloneNotSupportedException {
+        AgileEncryptionHeader other = (AgileEncryptionHeader)super.clone();
+        other.encryptedHmacKey = (encryptedHmacKey == null) ? null : encryptedHmacKey.clone();
+        other.encryptedHmacValue = (encryptedHmacValue == null) ? null : encryptedHmacValue.clone();
+        return other;
+    }
+
 }

Modified: poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptionInfoBuilder.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptionInfoBuilder.java?rev=1762726&r1=1762725&r2=1762726&view=diff
==============================================================================
--- poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptionInfoBuilder.java (original)
+++ poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptionInfoBuilder.java Wed Sep 28 23:36:09 2016
@@ -35,30 +35,24 @@ import com.microsoft.schemas.office.x200
 
 public class AgileEncryptionInfoBuilder implements EncryptionInfoBuilder {
     
-    EncryptionInfo info;
-    AgileEncryptionHeader header;
-    AgileEncryptionVerifier verifier;
-    AgileDecryptor decryptor;
-    AgileEncryptor encryptor;
-
     @Override
-    public void initialize(EncryptionInfo ei, LittleEndianInput dis) throws IOException {
-        this.info = ei;
-        
+    public void initialize(EncryptionInfo info, LittleEndianInput dis) throws IOException {
         EncryptionDocument ed = parseDescriptor((InputStream)dis);
-        header = new AgileEncryptionHeader(ed);
-        verifier = new AgileEncryptionVerifier(ed);
-        if (ei.getVersionMajor() == EncryptionMode.agile.versionMajor
-            && ei.getVersionMinor() == EncryptionMode.agile.versionMinor) {
-            decryptor = new AgileDecryptor(this);
-            encryptor = new AgileEncryptor(this);
+        info.setHeader(new AgileEncryptionHeader(ed));
+        info.setVerifier(new AgileEncryptionVerifier(ed));
+        if (info.getVersionMajor() == EncryptionMode.agile.versionMajor
+            && info.getVersionMinor() == EncryptionMode.agile.versionMinor) {
+            AgileDecryptor dec = new AgileDecryptor();
+            dec.setEncryptionInfo(info);
+            info.setDecryptor(dec);
+            AgileEncryptor enc = new AgileEncryptor();
+            enc.setEncryptionInfo(info);
+            info.setEncryptor(enc);
         }
     }
 
     @Override
-    public void initialize(EncryptionInfo ei, CipherAlgorithm cipherAlgorithm, HashAlgorithm hashAlgorithm, int keyBits, int blockSize, ChainingMode chainingMode) {
-        this.info = ei;
-
+    public void initialize(EncryptionInfo info, CipherAlgorithm cipherAlgorithm, HashAlgorithm hashAlgorithm, int keyBits, int blockSize, ChainingMode chainingMode) {
         if (cipherAlgorithm == null) {
             cipherAlgorithm = CipherAlgorithm.aes128;
         }
@@ -87,30 +81,14 @@ public class AgileEncryptionInfoBuilder
         if (!found) {
             throw new EncryptedDocumentException("KeySize "+keyBits+" not allowed for Cipher "+cipherAlgorithm.toString());
         }
-        header = new AgileEncryptionHeader(cipherAlgorithm, hashAlgorithm, keyBits, blockSize, chainingMode);
-        verifier = new AgileEncryptionVerifier(cipherAlgorithm, hashAlgorithm, keyBits, blockSize, chainingMode);
-        decryptor = new AgileDecryptor(this);
-        encryptor = new AgileEncryptor(this);
-    }
-    
-    public AgileEncryptionHeader getHeader() {
-        return header;
-    }
-
-    public AgileEncryptionVerifier getVerifier() {
-        return verifier;
-    }
-
-    public AgileDecryptor getDecryptor() {
-        return decryptor;
-    }
-
-    public AgileEncryptor getEncryptor() {
-        return encryptor;
-    }
-
-    protected EncryptionInfo getInfo() {
-        return info;
+        info.setHeader(new AgileEncryptionHeader(cipherAlgorithm, hashAlgorithm, keyBits, blockSize, chainingMode));
+        info.setVerifier(new AgileEncryptionVerifier(cipherAlgorithm, hashAlgorithm, keyBits, blockSize, chainingMode));
+        AgileDecryptor dec = new AgileDecryptor();
+        dec.setEncryptionInfo(info);
+        info.setDecryptor(dec);
+        AgileEncryptor enc = new AgileEncryptor();
+        enc.setEncryptionInfo(info);
+        info.setEncryptor(enc);
     }
     
     protected static EncryptionDocument parseDescriptor(String descriptor) {

Modified: poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptionVerifier.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptionVerifier.java?rev=1762726&r1=1762725&r2=1762726&view=diff
==============================================================================
--- poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptionVerifier.java (original)
+++ poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptionVerifier.java Wed Sep 28 23:36:09 2016
@@ -39,7 +39,7 @@ import com.microsoft.schemas.office.x200
 /**
  * Used when checking if a key is valid for a document 
  */
-public class AgileEncryptionVerifier extends EncryptionVerifier {
+public class AgileEncryptionVerifier extends EncryptionVerifier implements Cloneable {
 
     public static class AgileCertificateEntry {
         X509Certificate x509;
@@ -87,8 +87,9 @@ public class AgileEncryptionVerifier ext
         setEncryptedVerifierHash(keyData.getEncryptedVerifierHashValue());
 
         int saltSize = keyData.getSaltSize();
-        if (saltSize != getSalt().length)
+        if (saltSize != getSalt().length) {
             throw new EncryptedDocumentException("Invalid salt size");
+        }
         
         switch (keyData.getCipherChaining().intValue()) {
             case STCipherChaining.INT_CHAINING_MODE_CBC:
@@ -101,7 +102,9 @@ public class AgileEncryptionVerifier ext
                 throw new EncryptedDocumentException("Unsupported chaining mode - "+keyData.getCipherChaining().toString());
         }
         
-        if (!encList.hasNext()) return;
+        if (!encList.hasNext()) {
+            return;
+        }
         
         try {
             CertificateFactory cf = CertificateFactory.getInstance("X.509");
@@ -125,6 +128,7 @@ public class AgileEncryptionVerifier ext
         setSpinCount(100000); // TODO: use parameter
     }
     
+    @Override
     protected void setSalt(byte salt[]) {
         if (salt == null || salt.length != getCipherAlgorithm().blockSize) {
             throw new EncryptedDocumentException("invalid verifier salt");
@@ -133,16 +137,19 @@ public class AgileEncryptionVerifier ext
     }
     
     // make method visible for this package
+    @Override
     protected void setEncryptedVerifier(byte encryptedVerifier[]) {
         super.setEncryptedVerifier(encryptedVerifier);
     }
 
     // make method visible for this package
+    @Override
     protected void setEncryptedVerifierHash(byte encryptedVerifierHash[]) {
         super.setEncryptedVerifierHash(encryptedVerifierHash);
     }
 
     // make method visible for this package
+    @Override
     protected void setEncryptedKey(byte[] encryptedKey) {
         super.setEncryptedKey(encryptedKey);
     }
@@ -156,4 +163,12 @@ public class AgileEncryptionVerifier ext
     public List<AgileCertificateEntry> getCertificates() {
         return certList;
     }
+
+    @Override
+    public AgileEncryptionVerifier clone() throws CloneNotSupportedException {
+        AgileEncryptionVerifier other = (AgileEncryptionVerifier)super.clone();
+        // TODO: deep copy of certList
+        other.certList = new ArrayList<AgileCertificateEntry>(certList);
+        return other;
+    }
 }

Modified: poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptor.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptor.java?rev=1762726&r1=1762725&r2=1762726&view=diff
==============================================================================
--- poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptor.java (original)
+++ poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptor.java Wed Sep 28 23:36:09 2016
@@ -60,6 +60,7 @@ import org.apache.poi.poifs.crypt.standa
 import org.apache.poi.poifs.filesystem.DirectoryNode;
 import org.apache.poi.util.LittleEndian;
 import org.apache.poi.util.LittleEndianByteArrayOutputStream;
+import org.apache.poi.util.LittleEndianConsts;
 import org.apache.xmlbeans.XmlOptions;
 
 import com.microsoft.schemas.office.x2006.encryption.CTDataIntegrity;
@@ -74,21 +75,20 @@ import com.microsoft.schemas.office.x200
 import com.microsoft.schemas.office.x2006.keyEncryptor.certificate.CTCertificateKeyEncryptor;
 import com.microsoft.schemas.office.x2006.keyEncryptor.password.CTPasswordKeyEncryptor;
 
-public class AgileEncryptor extends Encryptor {
-    private final AgileEncryptionInfoBuilder builder;
+public class AgileEncryptor extends Encryptor implements Cloneable {
     private byte integritySalt[];
 	private byte pwHash[];
     
-	protected AgileEncryptor(AgileEncryptionInfoBuilder builder) {
-		this.builder = builder;
+	protected AgileEncryptor() {
 	}
 
+    @Override
     public void confirmPassword(String password) {
         // see [MS-OFFCRYPTO] - 2.3.3 EncryptionVerifier
         Random r = new SecureRandom();
-        int blockSize = builder.getHeader().getBlockSize();
-        int keySize = builder.getHeader().getKeySize()/8;
-        int hashSize = builder.getHeader().getHashAlgorithmEx().hashSize;
+        int blockSize = getEncryptionInfo().getHeader().getBlockSize();
+        int keySize = getEncryptionInfo().getHeader().getKeySize()/8;
+        int hashSize = getEncryptionInfo().getHeader().getHashAlgorithmEx().hashSize;
         
         byte[] newVerifierSalt = new byte[blockSize]
              , newVerifier = new byte[blockSize]
@@ -104,10 +104,11 @@ public class AgileEncryptor extends Encr
         confirmPassword(password, newKeySpec, newKeySalt, newVerifierSalt, newVerifier, newIntegritySalt);
     }
 	
-	public void confirmPassword(String password, byte keySpec[], byte keySalt[], byte verifier[], byte verifierSalt[], byte integritySalt[]) {
-        AgileEncryptionVerifier ver = builder.getVerifier();
+	@Override
+    public void confirmPassword(String password, byte keySpec[], byte keySalt[], byte verifier[], byte verifierSalt[], byte integritySalt[]) {
+        AgileEncryptionVerifier ver = (AgileEncryptionVerifier)getEncryptionInfo().getVerifier();
         ver.setSalt(verifierSalt);
-        AgileEncryptionHeader header = builder.getHeader();
+        AgileEncryptionHeader header = (AgileEncryptionHeader)getEncryptionInfo().getHeader();
         header.setKeySalt(keySalt);
         HashAlgorithm hashAlgo = ver.getHashAlgorithm();
 
@@ -128,7 +129,7 @@ public class AgileEncryptor extends Encr
          *    blockSize bytes.
          * 4. Use base64 to encode the result of step 3.
          */
-        byte encryptedVerifier[] = hashInput(builder, pwHash, kVerifierInputBlock, verifier, Cipher.ENCRYPT_MODE);
+        byte encryptedVerifier[] = hashInput(getEncryptionInfo(), pwHash, kVerifierInputBlock, verifier, Cipher.ENCRYPT_MODE);
         ver.setEncryptedVerifier(encryptedVerifier);
 	    
 
@@ -146,7 +147,7 @@ public class AgileEncryptor extends Encr
          */
         MessageDigest hashMD = getMessageDigest(hashAlgo);
         byte[] hashedVerifier = hashMD.digest(verifier);
-        byte encryptedVerifierHash[] = hashInput(builder, pwHash, kHashedVerifierBlock, hashedVerifier, Cipher.ENCRYPT_MODE);
+        byte encryptedVerifierHash[] = hashInput(getEncryptionInfo(), pwHash, kHashedVerifierBlock, hashedVerifier, Cipher.ENCRYPT_MODE);
         ver.setEncryptedVerifierHash(encryptedVerifierHash);
         
         /**
@@ -162,7 +163,7 @@ public class AgileEncryptor extends Encr
          *    blockSize bytes.
          * 4. Use base64 to encode the result of step 3.
          */
-        byte encryptedKey[] = hashInput(builder, pwHash, kCryptoKeyBlock, keySpec, Cipher.ENCRYPT_MODE);
+        byte encryptedKey[] = hashInput(getEncryptionInfo(), pwHash, kCryptoKeyBlock, keySpec, Cipher.ENCRYPT_MODE);
         ver.setEncryptedKey(encryptedKey);
         
         SecretKey secretKey = new SecretKeySpec(keySpec, ver.getCipherAlgorithm().jceId);
@@ -214,6 +215,7 @@ public class AgileEncryptor extends Encr
         }
 	}
 	
+    @Override
     public OutputStream getDataStream(DirectoryNode dir)
             throws IOException, GeneralSecurityException {
         // TODO: initialize headers
@@ -234,14 +236,14 @@ public class AgileEncryptor extends Encr
         // as the integrity hmac needs to contain the StreamSize,
         // it's not possible to calculate it on-the-fly while buffering
         // TODO: add stream size parameter to getDataStream()
-        AgileEncryptionVerifier ver = builder.getVerifier();
+        AgileEncryptionVerifier ver = (AgileEncryptionVerifier)getEncryptionInfo().getVerifier();
         HashAlgorithm hashAlgo = ver.getHashAlgorithm();
         Mac integrityMD = CryptoFunctions.getMac(hashAlgo);
         integrityMD.init(new SecretKeySpec(integritySalt, hashAlgo.jceHmacId));
 
         byte buf[] = new byte[1024];
         LittleEndian.putLong(buf, 0, oleStreamSize);
-        integrityMD.update(buf, 0, LittleEndian.LONG_SIZE);
+        integrityMD.update(buf, 0, LittleEndianConsts.LONG_SIZE);
         
         InputStream fis = new FileInputStream(tmpFile);
         try {
@@ -255,7 +257,7 @@ public class AgileEncryptor extends Encr
         
         byte hmacValue[] = integrityMD.doFinal();
         
-        AgileEncryptionHeader header = builder.getHeader();
+        AgileEncryptionHeader header = (AgileEncryptionHeader)getEncryptionInfo().getHeader();
         int blockSize = header.getBlockSize();
         byte iv[] = CryptoFunctions.generateIv(header.getHashAlgorithmEx(), header.getKeySalt(), kIntegrityValueBlock, blockSize);
         Cipher cipher = CryptoFunctions.getCipher(getSecretKey(), header.getCipherAlgorithm(), header.getChainingMode(), iv, Cipher.ENCRYPT_MODE);
@@ -271,8 +273,8 @@ public class AgileEncryptor extends Encr
         CTKeyEncryptor.Uri.HTTP_SCHEMAS_MICROSOFT_COM_OFFICE_2006_KEY_ENCRYPTOR_CERTIFICATE;
     
     protected EncryptionDocument createEncryptionDocument() {
-        AgileEncryptionVerifier ver = builder.getVerifier();
-        AgileEncryptionHeader header = builder.getHeader(); 
+        AgileEncryptionVerifier ver = (AgileEncryptionVerifier)getEncryptionInfo().getVerifier();
+        AgileEncryptionHeader header = (AgileEncryptionHeader)getEncryptionInfo().getHeader(); 
         
         EncryptionDocument ed = EncryptionDocument.Factory.newInstance();
         CTEncryption edRoot = ed.addNewEncryption();
@@ -379,9 +381,10 @@ public class AgileEncryptor extends Encr
     throws IOException, GeneralSecurityException {
         DataSpaceMapUtils.addDefaultDataSpace(dir);
 
-        final EncryptionInfo info = builder.getInfo();
+        final EncryptionInfo info = getEncryptionInfo();
 
         EncryptionRecord er = new EncryptionRecord(){
+            @Override
             public void write(LittleEndianByteArrayOutputStream bos) {
                 // EncryptionVersionInfo (4 bytes): A Version structure (section 2.1.4), where 
                 // Version.vMajor MUST be 0x0004 and Version.vMinor MUST be 0x0004
@@ -422,7 +425,7 @@ public class AgileEncryptor extends Encr
         @Override
         protected Cipher initCipherForBlock(Cipher existing, int block, boolean lastChunk)
         throws GeneralSecurityException {
-            return AgileDecryptor.initCipherForBlock(existing, block, lastChunk, builder, getSecretKey(), Cipher.ENCRYPT_MODE);
+            return AgileDecryptor.initCipherForBlock(existing, block, lastChunk, getEncryptionInfo(), getSecretKey(), Cipher.ENCRYPT_MODE);
         }
 
         @Override
@@ -439,4 +442,11 @@ public class AgileEncryptor extends Encr
         }
     }
 
+    @Override
+    public AgileEncryptor clone() throws CloneNotSupportedException {
+        AgileEncryptor other = (AgileEncryptor)super.clone();
+        other.integritySalt = (integritySalt == null) ? null : integritySalt.clone();
+        other.pwHash = (pwHash == null) ? null : pwHash.clone();
+        return other;
+    }
 }

Modified: poi/trunk/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestAgileEncryptionParameters.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestAgileEncryptionParameters.java?rev=1762726&r1=1762725&r2=1762726&view=diff
==============================================================================
--- poi/trunk/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestAgileEncryptionParameters.java (original)
+++ poi/trunk/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestAgileEncryptionParameters.java Wed Sep 28 23:36:09 2016
@@ -16,8 +16,7 @@
 ==================================================================== */
 package org.apache.poi.poifs.crypt;
 
-import static org.hamcrest.core.IsEqual.equalTo;
-import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertTrue;
 
 import java.io.ByteArrayInputStream;
@@ -94,6 +93,7 @@ public class TestAgileEncryptionParamete
         os.close();
         bos.reset();
         fsEnc.writeFilesystem(bos);
+        fsEnc.close();
         
         POIFSFileSystem fsDec = new POIFSFileSystem(new ByteArrayInputStream(bos.toByteArray()));
         EncryptionInfo infoDec = new EncryptionInfo(fsDec);
@@ -103,6 +103,7 @@ public class TestAgileEncryptionParamete
         InputStream is = dec.getDataStream(fsDec);
         byte actualData[] = IOUtils.toByteArray(is);
         is.close();
-        assertThat("Failed roundtrip - "+ca+"-"+ha+"-"+cm, testData, equalTo(actualData));
+        fsDec.close();
+        assertArrayEquals("Failed roundtrip - "+ca+"-"+ha+"-"+cm, testData, actualData);
     }
 }

Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/DocumentEncryptionAtom.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/DocumentEncryptionAtom.java?rev=1762726&r1=1762725&r2=1762726&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/DocumentEncryptionAtom.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hslf/record/DocumentEncryptionAtom.java Wed Sep 28 23:36:09 2016
@@ -53,7 +53,8 @@ public final class DocumentEncryptionAto
 
 		ByteArrayInputStream bis = new ByteArrayInputStream(source, start+8, len-8);
 		LittleEndianInputStream leis = new LittleEndianInputStream(bis);
-		ei = new EncryptionInfo(leis, true);
+		ei = new EncryptionInfo(leis, EncryptionMode.cryptoAPI);
+		leis.close();
 	}
 
 	public DocumentEncryptionAtom() {
@@ -121,6 +122,7 @@ public final class DocumentEncryptionAto
 		LittleEndian.putInt(_header, 4, bos.getWriteIndex());
         out.write(_header);
 		out.write(data, 0, bos.getWriteIndex());
+		bos.close();
 	}
 
     @Override

Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShowEncrypted.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShowEncrypted.java?rev=1762726&r1=1762725&r2=1762726&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShowEncrypted.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShowEncrypted.java Wed Sep 28 23:36:09 2016
@@ -17,6 +17,8 @@
 
 package org.apache.poi.hslf.usermodel;
 
+import java.io.Closeable;
+import java.io.IOException;
 import java.io.OutputStream;
 import java.security.GeneralSecurityException;
 import java.util.ArrayList;
@@ -25,9 +27,6 @@ import java.util.Map;
 import java.util.NavigableMap;
 import java.util.TreeMap;
 
-import javax.crypto.Cipher;
-import javax.crypto.CipherOutputStream;
-
 import org.apache.poi.hslf.exceptions.CorruptPowerPointFileException;
 import org.apache.poi.hslf.exceptions.EncryptedPowerPointFileException;
 import org.apache.poi.hslf.record.DocumentEncryptionAtom;
@@ -36,26 +35,45 @@ import org.apache.poi.hslf.record.Positi
 import org.apache.poi.hslf.record.Record;
 import org.apache.poi.hslf.record.UserEditAtom;
 import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
+import org.apache.poi.poifs.crypt.ChunkedCipherInputStream;
+import org.apache.poi.poifs.crypt.ChunkedCipherOutputStream;
 import org.apache.poi.poifs.crypt.Decryptor;
 import org.apache.poi.poifs.crypt.EncryptionInfo;
 import org.apache.poi.poifs.crypt.cryptoapi.CryptoAPIDecryptor;
 import org.apache.poi.poifs.crypt.cryptoapi.CryptoAPIEncryptor;
 import org.apache.poi.util.BitField;
+import org.apache.poi.util.IOUtils;
 import org.apache.poi.util.Internal;
 import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.LittleEndianByteArrayInputStream;
+import org.apache.poi.util.LittleEndianByteArrayOutputStream;
 
 /**
  * This class provides helper functions for encrypted PowerPoint documents.
  */
 @Internal
-public class HSLFSlideShowEncrypted {
+public class HSLFSlideShowEncrypted implements Closeable {
     DocumentEncryptionAtom dea;
     CryptoAPIEncryptor enc = null;
     CryptoAPIDecryptor dec = null;
-    Cipher cipher = null;
-    CipherOutputStream cyos = null;
+//    Cipher cipher = null;
+    ChunkedCipherOutputStream cyos = null;
 
     private static final BitField fieldRecInst = new BitField(0xFFF0);
+
+    private static final int BLIB_STORE_ENTRY_PARTS[] = {
+        1,     // btWin32
+        1,     // btMacOS
+        16,    // rgbUid
+        2,     // tag
+        4,     // size
+        4,     // cRef
+        4,     // foDelay
+        1,     // unused1
+        1,     // cbName (@ index 33)
+        1,     // unused2
+        1,     // unused3
+    };
     
     protected HSLFSlideShowEncrypted(DocumentEncryptionAtom dea) {
         this.dea = dea;
@@ -67,7 +85,9 @@ public class HSLFSlideShowEncrypted {
         UserEditAtom userEditAtomWithEncryption = null;
         for (Map.Entry<Integer, Record> me : recordMap.descendingMap().entrySet()) {
             Record r = me.getValue();
-            if (!(r instanceof UserEditAtom)) continue;
+            if (!(r instanceof UserEditAtom)) {
+                continue;
+            }
             UserEditAtom uea = (UserEditAtom)r;
             if (uea.getEncryptSessionPersistIdRef() != -1) {
                 userEditAtomWithEncryption = uea;
@@ -83,7 +103,7 @@ public class HSLFSlideShowEncrypted {
         Record r = recordMap.get(userEditAtomWithEncryption.getPersistPointersOffset());
         assert(r instanceof PersistPtrHolder);
         PersistPtrHolder ptr = (PersistPtrHolder)r;
-        
+
         Integer encOffset = ptr.getSlideLocationsLookup().get(userEditAtomWithEncryption.getEncryptSessionPersistIdRef());
         if (encOffset == null) {
             // encryption info doesn't exist anymore
@@ -91,7 +111,7 @@ public class HSLFSlideShowEncrypted {
             dea = null;
             return;
         }
-        
+
         r = recordMap.get(encOffset);
         if (r == null) {
             r = Record.buildRecordAtOffset(docstream, encOffset);
@@ -100,7 +120,7 @@ public class HSLFSlideShowEncrypted {
         assert(r instanceof DocumentEncryptionAtom);
         this.dea = (DocumentEncryptionAtom)r;
         decryptInit();
-        
+
         String pass = Biff8EncryptionKey.getCurrentUserPassword();
         if(!dec.verifyPassword(pass != null ? pass : Decryptor.DEFAULT_PASSWORD)) {
             throw new EncryptedPowerPointFileException("PowerPoint file is encrypted. The correct password needs to be set via Biff8EncryptionKey.setCurrentUserPassword()");
@@ -110,119 +130,144 @@ public class HSLFSlideShowEncrypted {
     public DocumentEncryptionAtom getDocumentEncryptionAtom() {
         return dea;
     }
-    
-    protected void setPersistId(int persistId) {
-        if (enc != null && dec != null) {
-            throw new EncryptedPowerPointFileException("Use instance either for en- or decryption");
-        }
-        
-        try {
-            if (enc != null) cipher = enc.initCipherForBlock(cipher, persistId);
-            if (dec != null) cipher = dec.initCipherForBlock(cipher, persistId);
-        } catch (GeneralSecurityException e) {
-            throw new EncryptedPowerPointFileException(e);
-        }
-    }
-    
+
     protected void decryptInit() {
-        if (dec != null) return;
+        if (dec != null) {
+            return;
+        }
         EncryptionInfo ei = dea.getEncryptionInfo();
         dec = (CryptoAPIDecryptor)ei.getDecryptor();
     }
-    
+
     protected void encryptInit() {
-        if (enc != null) return;
+        if (enc != null) {
+            return;
+        }
         EncryptionInfo ei = dea.getEncryptionInfo();
         enc = (CryptoAPIEncryptor)ei.getEncryptor();
     }
-    
 
-    
+
+
     protected OutputStream encryptRecord(OutputStream plainStream, int persistId, Record record) {
-        boolean isPlain = (dea == null 
+        boolean isPlain = (dea == null
             || record instanceof UserEditAtom
             || record instanceof PersistPtrHolder
             || record instanceof DocumentEncryptionAtom
         );
-        if (isPlain) return plainStream;
 
-        encryptInit();
-        setPersistId(persistId);
-        
-        if (cyos == null) {
-            cyos = new CipherOutputStream(plainStream, cipher);
+        try {
+            if (isPlain) {
+                if (cyos != null) {
+                    // write cached data to stream
+                    cyos.flush();
+                }
+                return plainStream;
+            }
+
+            encryptInit();
+
+            if (cyos == null) {
+                enc.setChunkSize(-1);
+                cyos = enc.getDataStream(plainStream, 0);
+            }
+            cyos.initCipherForBlock(persistId, false);
+        } catch (Exception e) {
+            throw new EncryptedPowerPointFileException(e);
         }
         return cyos;
     }
 
+    private static void readFully(ChunkedCipherInputStream ccis, byte[] docstream, int offset, int len) throws IOException {
+        if (IOUtils.readFully(ccis, docstream, offset, len) == -1) {
+            throw new EncryptedPowerPointFileException("unexpected EOF");
+        }
+    }
+
     protected void decryptRecord(byte[] docstream, int persistId, int offset) {
-        if (dea == null) return;
+        if (dea == null) {
+            return;
+        }
 
         decryptInit();
-        setPersistId(persistId);
-        
+        dec.setChunkSize(-1);
+        LittleEndianByteArrayInputStream lei = new LittleEndianByteArrayInputStream(docstream, offset);
+        ChunkedCipherInputStream ccis = null;
         try {
+            ccis = dec.getDataStream(lei, docstream.length-offset, 0);
+            ccis.initCipherForBlock(persistId);
+
             // decrypt header and read length to be decrypted
-            cipher.update(docstream, offset, 8, docstream, offset);
+            readFully(ccis, docstream, offset, 8);
             // decrypt the rest of the record
             int rlen = (int)LittleEndian.getUInt(docstream, offset+4);
-            cipher.update(docstream, offset+8, rlen, docstream, offset+8);
-        } catch (GeneralSecurityException e) {
-            throw new CorruptPowerPointFileException(e);
-        }       
-    }        
+            readFully(ccis, docstream, offset+8, rlen);
+
+        } catch (Exception e) {
+            throw new EncryptedPowerPointFileException(e);
+        } finally {
+            try {
+                if (ccis != null) {
+                    ccis.close();
+                }
+                lei.close();
+            } catch (IOException e) {
+                throw new EncryptedPowerPointFileException(e);
+            }
+        }
+    }
+
+    private void decryptPicBytes(byte[] pictstream, int offset, int len)
+    throws IOException, GeneralSecurityException {
+        // when reading the picture elements, each time a segment is read, the cipher needs
+        // to be reset (usually done when calling Cipher.doFinal)
+        LittleEndianByteArrayInputStream lei = new LittleEndianByteArrayInputStream(pictstream, offset);
+        ChunkedCipherInputStream ccis = dec.getDataStream(lei, len, 0);
+        readFully(ccis, pictstream, offset, len);
+        ccis.close();
+        lei.close();
+    }
     
     protected void decryptPicture(byte[] pictstream, int offset) {
-        if (dea == null) return;
-        
+        if (dea == null) {
+            return;
+        }
+
         decryptInit();
-        setPersistId(0);
-        
+
         try {
             // decrypt header and read length to be decrypted
-            cipher.doFinal(pictstream, offset, 8, pictstream, offset);
+            decryptPicBytes(pictstream, offset, 8);
             int recInst = fieldRecInst.getValue(LittleEndian.getUShort(pictstream, offset));
             int recType = LittleEndian.getUShort(pictstream, offset+2);
             int rlen = (int)LittleEndian.getUInt(pictstream, offset+4);
             offset += 8;
-            int endOffset = offset + rlen; 
+            int endOffset = offset + rlen;
 
             if (recType == 0xF007) {
                 // TOOD: get a real example file ... to actual test the FBSE entry
                 // not sure where the foDelay block is
-                
+
                 // File BLIP Store Entry (FBSE)
-                cipher.doFinal(pictstream, offset, 1, pictstream, offset); // btWin32
-                offset++;
-                cipher.doFinal(pictstream, offset, 1, pictstream, offset); // btMacOS
-                offset++;
-                cipher.doFinal(pictstream, offset, 16, pictstream, offset); // rgbUid
-                offset += 16;
-                cipher.doFinal(pictstream, offset, 2, pictstream, offset); // tag
-                offset += 2;
-                cipher.doFinal(pictstream, offset, 4, pictstream, offset); // size
-                offset += 4;
-                cipher.doFinal(pictstream, offset, 4, pictstream, offset); // cRef
-                offset += 4;
-                cipher.doFinal(pictstream, offset, 4, pictstream, offset); // foDelay
-                offset += 4;
-                cipher.doFinal(pictstream, offset+0, 1, pictstream, offset+0); // unused1
-                cipher.doFinal(pictstream, offset+1, 1, pictstream, offset+1); // cbName
-                cipher.doFinal(pictstream, offset+2, 1, pictstream, offset+2); // unused2
-                cipher.doFinal(pictstream, offset+3, 1, pictstream, offset+3); // unused3
-                int cbName = LittleEndian.getUShort(pictstream, offset+1);
-                offset += 4;
+                for (int part : BLIB_STORE_ENTRY_PARTS) {
+                    decryptPicBytes(pictstream, offset, part);
+                }
+                offset += 36;
+                
+                int cbName = LittleEndian.getUShort(pictstream, offset-3);
                 if (cbName > 0) {
-                    cipher.doFinal(pictstream, offset, cbName, pictstream, offset); // nameData
+                    // read nameData
+                    decryptPicBytes(pictstream, offset, cbName);
                     offset += cbName;
                 }
+                
                 if (offset == endOffset) {
                     return; // no embedded blip
                 }
                 // fall through, read embedded blip now
 
                 // update header data
-                cipher.doFinal(pictstream, offset, 8, pictstream, offset);
+                decryptPicBytes(pictstream, offset, 8);
                 recInst = fieldRecInst.getValue(LittleEndian.getUShort(pictstream, offset));
                 recType = LittleEndian.getUShort(pictstream, offset+2);
                 // rlen = (int)LittleEndian.getUInt(pictstream, offset+4);
@@ -231,70 +276,73 @@ public class HSLFSlideShowEncrypted {
 
             int rgbUidCnt = (recInst == 0x217 || recInst == 0x3D5 || recInst == 0x46B || recInst == 0x543 ||
                 recInst == 0x6E1 || recInst == 0x6E3 || recInst == 0x6E5 || recInst == 0x7A9) ? 2 : 1;
-            
+
+            // rgbUid 1/2
             for (int i=0; i<rgbUidCnt; i++) {
-                cipher.doFinal(pictstream, offset, 16, pictstream, offset); // rgbUid 1/2
+                decryptPicBytes(pictstream, offset, 16);
                 offset += 16;
             }
-            
+
+            int nextBytes;
             if (recType == 0xF01A || recType == 0XF01B || recType == 0XF01C) {
-                cipher.doFinal(pictstream, offset, 34, pictstream, offset); // metafileHeader
-                offset += 34;
+                // metafileHeader
+                nextBytes = 34;
             } else {
-                cipher.doFinal(pictstream, offset, 1, pictstream, offset); // tag
-                offset += 1;
+                // tag
+                nextBytes = 1;
             }
             
+            decryptPicBytes(pictstream, offset, nextBytes);
+            offset += nextBytes;
+
             int blipLen = endOffset - offset;
-            cipher.doFinal(pictstream, offset, blipLen, pictstream, offset);
-        } catch (GeneralSecurityException e) {
+            decryptPicBytes(pictstream, offset, blipLen);
+        } catch (Exception e) {
             throw new CorruptPowerPointFileException(e);
-        }       
+        }
     }
 
     protected void encryptPicture(byte[] pictstream, int offset) {
-        if (dea == null) return;
-        
+        if (dea == null) {
+            return;
+        }
+
         encryptInit();
-        setPersistId(0);
+
+        LittleEndianByteArrayOutputStream los = new LittleEndianByteArrayOutputStream(pictstream, offset);
+        ChunkedCipherOutputStream ccos = null;
 
         try {
+            enc.setChunkSize(-1);
+            ccos = enc.getDataStream(los, 0);
             int recInst = fieldRecInst.getValue(LittleEndian.getUShort(pictstream, offset));
             int recType = LittleEndian.getUShort(pictstream, offset+2);
-            int rlen = (int)LittleEndian.getUInt(pictstream, offset+4);
-            cipher.doFinal(pictstream, offset, 8, pictstream, offset);
+            final int rlen = (int)LittleEndian.getUInt(pictstream, offset+4);
+
+            ccos.write(pictstream, offset, 8);
+            ccos.flush();
             offset += 8;
-            int endOffset = offset + rlen; 
+            int endOffset = offset + rlen;
 
             if (recType == 0xF007) {
                 // TOOD: get a real example file ... to actual test the FBSE entry
                 // not sure where the foDelay block is
-                
+
                 // File BLIP Store Entry (FBSE)
-                cipher.doFinal(pictstream, offset, 1, pictstream, offset); // btWin32
-                offset++;
-                cipher.doFinal(pictstream, offset, 1, pictstream, offset); // btMacOS
-                offset++;
-                cipher.doFinal(pictstream, offset, 16, pictstream, offset); // rgbUid
-                offset += 16;
-                cipher.doFinal(pictstream, offset, 2, pictstream, offset); // tag
-                offset += 2;
-                cipher.doFinal(pictstream, offset, 4, pictstream, offset); // size
-                offset += 4;
-                cipher.doFinal(pictstream, offset, 4, pictstream, offset); // cRef
-                offset += 4;
-                cipher.doFinal(pictstream, offset, 4, pictstream, offset); // foDelay
-                offset += 4;
-                int cbName = LittleEndian.getUShort(pictstream, offset+1);
-                cipher.doFinal(pictstream, offset+0, 1, pictstream, offset+0); // unused1
-                cipher.doFinal(pictstream, offset+1, 1, pictstream, offset+1); // cbName
-                cipher.doFinal(pictstream, offset+2, 1, pictstream, offset+2); // unused2
-                cipher.doFinal(pictstream, offset+3, 1, pictstream, offset+3); // unused3
-                offset += 4;
+                int cbName = LittleEndian.getUShort(pictstream, offset+33);
+                
+                for (int part : BLIB_STORE_ENTRY_PARTS) {
+                    ccos.write(pictstream, offset, part);
+                    ccos.flush();
+                    offset += part;
+                }
+                
                 if (cbName > 0) {
-                    cipher.doFinal(pictstream, offset, cbName, pictstream, offset); // nameData
+                    ccos.write(pictstream, offset, cbName);
+                    ccos.flush();
                     offset += cbName;
                 }
+                
                 if (offset == endOffset) {
                     return; // no embedded blip
                 }
@@ -303,32 +351,45 @@ public class HSLFSlideShowEncrypted {
                 // update header data
                 recInst = fieldRecInst.getValue(LittleEndian.getUShort(pictstream, offset));
                 recType = LittleEndian.getUShort(pictstream, offset+2);
-                // rlen = (int) LittleEndian.getUInt(pictstream, offset+4);
-                cipher.doFinal(pictstream, offset, 8, pictstream, offset);
+                ccos.write(pictstream, offset, 8);
+                ccos.flush();
                 offset += 8;
             }
-            
+
             int rgbUidCnt = (recInst == 0x217 || recInst == 0x3D5 || recInst == 0x46B || recInst == 0x543 ||
                 recInst == 0x6E1 || recInst == 0x6E3 || recInst == 0x6E5 || recInst == 0x7A9) ? 2 : 1;
-                
+
             for (int i=0; i<rgbUidCnt; i++) {
-                cipher.doFinal(pictstream, offset, 16, pictstream, offset); // rgbUid 1/2
+                ccos.write(pictstream, offset, 16); // rgbUid 1/2
+                ccos.flush();
                 offset += 16;
             }
-            
+
             if (recType == 0xF01A || recType == 0XF01B || recType == 0XF01C) {
-                cipher.doFinal(pictstream, offset, 34, pictstream, offset); // metafileHeader
+                ccos.write(pictstream, offset, 34); // metafileHeader
                 offset += 34;
+                ccos.flush();
             } else {
-                cipher.doFinal(pictstream, offset, 1, pictstream, offset); // tag
+                ccos.write(pictstream, offset, 1); // tag
                 offset += 1;
+                ccos.flush();
             }
-            
+
             int blipLen = endOffset - offset;
-            cipher.doFinal(pictstream, offset, blipLen, pictstream, offset);
-        } catch (GeneralSecurityException e) {
-            throw new CorruptPowerPointFileException(e);
-        }       
+            ccos.write(pictstream, offset, blipLen);
+            ccos.flush();
+        } catch (Exception e) {
+            throw new EncryptedPowerPointFileException(e);
+        } finally {
+            try {
+                if (ccos != null) {
+                    ccos.close();
+                }
+                los.close();
+            } catch (IOException e) {
+                throw new EncryptedPowerPointFileException(e);
+            }
+        }
     }
 
     protected Record[] updateEncryptionRecord(Record records[]) {
@@ -372,7 +433,7 @@ public class HSLFSlideShowEncrypted {
     protected static Record[] normalizeRecords(Record records[]) {
         // http://msdn.microsoft.com/en-us/library/office/gg615594(v=office.14).aspx
         // repeated slideIds can be overwritten, i.e. ignored
-        
+
         UserEditAtom uea = null;
         PersistPtrHolder pph = null;
         TreeMap<Integer,Integer> slideLocations = new TreeMap<Integer,Integer>();
@@ -386,7 +447,7 @@ public class HSLFSlideShowEncrypted {
                 uea = (UserEditAtom)pdr;
                 continue;
             }
-            
+
             if (pdr instanceof PersistPtrHolder) {
                 if (pph != null) {
                     duplicatedCount++;
@@ -394,16 +455,18 @@ public class HSLFSlideShowEncrypted {
                 pph = (PersistPtrHolder)pdr;
                 for (Map.Entry<Integer,Integer> me : pph.getSlideLocationsLookup().entrySet()) {
                     Integer oldOffset = slideLocations.put(me.getKey(), me.getValue());
-                    if (oldOffset != null) obsoleteOffsets.add(oldOffset);
+                    if (oldOffset != null) {
+                        obsoleteOffsets.add(oldOffset);
+                    }
                 }
                 continue;
             }
-            
+
             recordMap.put(pdr.getLastOnDiskOffset(), r);
         }
-        
+
         assert(uea != null && pph != null && uea.getPersistPointersOffset() == pph.getLastOnDiskOffset());
-        
+
         recordMap.put(pph.getLastOnDiskOffset(), pph);
         recordMap.put(uea.getLastOnDiskOffset(), uea);
 
@@ -416,15 +479,15 @@ public class HSLFSlideShowEncrypted {
         for (Map.Entry<Integer,Integer> me : slideLocations.entrySet()) {
             pph.addSlideLookup(me.getKey(), me.getValue());
         }
-        
+
         for (Integer oldOffset : obsoleteOffsets) {
             recordMap.remove(oldOffset);
         }
-        
+
         return recordMap.values().toArray(new Record[recordMap.size()]);
     }
-     
-    
+
+
     protected static Record[] removeEncryptionRecord(Record records[]) {
         int deaSlideId = -1;
         int deaOffset = -1;
@@ -444,23 +507,27 @@ public class HSLFSlideShowEncrypted {
             }
             recordList.add(r);
         }
-        
+
         assert(ptr != null);
-        if (deaSlideId == -1 && deaOffset == -1) return records;
-        
+        if (deaSlideId == -1 && deaOffset == -1) {
+            return records;
+        }
+
         TreeMap<Integer,Integer> tm = new TreeMap<Integer,Integer>(ptr.getSlideLocationsLookup());
         ptr.clear();
         int maxSlideId = -1;
         for (Map.Entry<Integer,Integer> me : tm.entrySet()) {
-            if (me.getKey() == deaSlideId || me.getValue() == deaOffset) continue;
+            if (me.getKey() == deaSlideId || me.getValue() == deaOffset) {
+                continue;
+            }
             ptr.addSlideLookup(me.getKey(), me.getValue());
             maxSlideId = Math.max(me.getKey(), maxSlideId);
         }
-        
+
         uea.setMaxPersistWritten(maxSlideId);
 
         records = recordList.toArray(new Record[recordList.size()]);
-        
+
         return records;
     }
 
@@ -470,9 +537,13 @@ public class HSLFSlideShowEncrypted {
         int ueaIdx = -1, ptrIdx = -1, deaIdx = -1, idx = -1;
         for (Record r : records) {
             idx++;
-            if (r instanceof UserEditAtom) ueaIdx = idx;
-            else if (r instanceof PersistPtrHolder) ptrIdx = idx;
-            else if (r instanceof DocumentEncryptionAtom) deaIdx = idx;
+            if (r instanceof UserEditAtom) {
+                ueaIdx = idx;
+            } else if (r instanceof PersistPtrHolder) {
+                ptrIdx = idx;
+            } else if (r instanceof DocumentEncryptionAtom) {
+                deaIdx = idx;
+            }
         }
         assert(ueaIdx != -1 && ptrIdx != -1 && ptrIdx < ueaIdx);
         if (deaIdx != -1) {
@@ -488,13 +559,22 @@ public class HSLFSlideShowEncrypted {
             ptr.addSlideLookup(nextSlideId, ptr.getLastOnDiskOffset()-1);
             uea.setEncryptSessionPersistIdRef(nextSlideId);
             uea.setMaxPersistWritten(nextSlideId);
-            
+
             Record newRecords[] = new Record[records.length+1];
-            if (ptrIdx > 0) System.arraycopy(records, 0, newRecords, 0, ptrIdx);
-            if (ptrIdx < records.length-1) System.arraycopy(records, ptrIdx, newRecords, ptrIdx+1, records.length-ptrIdx);
+            if (ptrIdx > 0) {
+                System.arraycopy(records, 0, newRecords, 0, ptrIdx);
+            }
+            if (ptrIdx < records.length-1) {
+                System.arraycopy(records, ptrIdx, newRecords, ptrIdx+1, records.length-ptrIdx);
+            }
             newRecords[ptrIdx] = dea;
             return newRecords;
         }
     }
 
+    public void close() throws IOException {
+        if (cyos != null) {
+            cyos.close();
+        }
+    }
 }

Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShowImpl.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShowImpl.java?rev=1762726&r1=1762725&r2=1762726&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShowImpl.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShowImpl.java Wed Sep 28 23:36:09 2016
@@ -54,6 +54,7 @@ import org.apache.poi.poifs.filesystem.E
 import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
 import org.apache.poi.poifs.filesystem.POIFSFileSystem;
 import org.apache.poi.sl.usermodel.PictureData.PictureType;
+import org.apache.poi.util.IOUtils;
 import org.apache.poi.util.LittleEndian;
 import org.apache.poi.util.POILogFactory;
 import org.apache.poi.util.POILogger;
@@ -205,14 +206,12 @@ public final class HSLFSlideShowImpl ext
 
 		// Grab the document stream
 		int len = docProps.getSize();
-		_docstream = new byte[len];
-		InputStream is = directory.createDocumentInputStream("PowerPoint Document");
-		int readLen = is.read(_docstream);
-		is.close();
-		
-		if (len != readLen) {
-		    throw new IOException("Document input stream ended prematurely - expected "+len+" bytes - received "+readLen+" bytes");
-		}
+        InputStream is = directory.createDocumentInputStream("PowerPoint Document");
+        try {
+            _docstream = IOUtils.toByteArray(is, len);
+        } finally {
+            is.close();
+        }
 	}
 
 	/**
@@ -364,17 +363,10 @@ public final class HSLFSlideShowImpl ext
         HSLFSlideShowEncrypted decryptData = new HSLFSlideShowEncrypted(getDocumentEncryptionAtom());
         
 		DocumentEntry entry = (DocumentEntry)directory.getEntry("Pictures");
-		int len = entry.getSize();
-		byte[] pictstream = new byte[len];
-		DocumentInputStream is = directory.createDocumentInputStream(entry);
-		int readLen = is.read(pictstream);
+        DocumentInputStream is = directory.createDocumentInputStream(entry);
+		byte[] pictstream = IOUtils.toByteArray(is, entry.getSize());
 		is.close();
 
-		if (len != readLen) {
-		    throw new IOException("Picture stream ended prematurely - expected "+len+" bytes - received "+readLen+" bytes");
-		}
-
-		
         int pos = 0;
 		// An empty picture record (length 0) will take up 8 bytes
         while (pos <= (pictstream.length-8)) {
@@ -512,7 +504,7 @@ public final class HSLFSlideShowImpl ext
         }
         
         HSLFSlideShowEncrypted encData = new HSLFSlideShowEncrypted(getDocumentEncryptionAtom());
-	    
+        
 	    for (Record record : _records) {
             assert(record instanceof PositionDependentRecord);
             // We've already figured out their new location, and
@@ -533,6 +525,8 @@ public final class HSLFSlideShowImpl ext
                 record.writeOut(encData.encryptRecord(os, persistId, record));
             }
         }
+	    
+	    encData.close();
 
         // Update and write out the Current User atom
         int oldLastUserEditAtomPos = (int)currentUser.getCurrentEditOffset();
@@ -733,7 +727,7 @@ public final class HSLFSlideShowImpl ext
         if (dea != null) {
             CryptoAPIEncryptor enc = (CryptoAPIEncryptor)dea.getEncryptionInfo().getEncryptor();
             try {
-                enc.getDataStream(outFS.getRoot()); // ignore OutputStream
+                enc.getSummaryEntries(outFS.getRoot()); // ignore OutputStream
             } catch (IOException e) {
                 throw e;
             } catch (GeneralSecurityException e) {

Modified: poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/record/TestDocumentEncryption.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/record/TestDocumentEncryption.java?rev=1762726&r1=1762725&r2=1762726&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/record/TestDocumentEncryption.java (original)
+++ poi/trunk/src/scratchpad/testcases/org/apache/poi/hslf/record/TestDocumentEncryption.java Wed Sep 28 23:36:09 2016
@@ -44,6 +44,7 @@ import org.apache.poi.hssf.record.crypto
 import org.apache.poi.poifs.crypt.CryptoFunctions;
 import org.apache.poi.poifs.crypt.EncryptionInfo;
 import org.apache.poi.poifs.crypt.HashAlgorithm;
+import org.apache.poi.poifs.crypt.cryptoapi.CryptoAPIDecryptor;
 import org.apache.poi.poifs.crypt.cryptoapi.CryptoAPIEncryptionHeader;
 import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
 import org.apache.poi.poifs.filesystem.POIFSFileSystem;
@@ -176,7 +177,7 @@ public class TestDocumentEncryption {
         
         DocumentEncryptionAtom dea = hss.getDocumentEncryptionAtom();
         
-        POIFSFileSystem fs2 = new POIFSFileSystem(dea.getEncryptionInfo().getDecryptor().getDataStream(fs));
+        POIFSFileSystem fs2 = ((CryptoAPIDecryptor)dea.getEncryptionInfo().getDecryptor()).getSummaryEntries(fs.getRoot(), "EncryptedSummary");
         PropertySet ps = PropertySetFactory.create(fs2.getRoot(), SummaryInformation.DEFAULT_STREAM_NAME);
         assertTrue(ps.isSummaryInformation());
         assertEquals("RC4 CryptoAPI Encryption", ps.getProperties()[1].getValue());

Modified: poi/trunk/src/testcases/org/apache/poi/hssf/record/AllRecordTests.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/hssf/record/AllRecordTests.java?rev=1762726&r1=1762725&r2=1762726&view=diff
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/hssf/record/AllRecordTests.java (original)
+++ poi/trunk/src/testcases/org/apache/poi/hssf/record/AllRecordTests.java Wed Sep 28 23:36:09 2016
@@ -21,8 +21,8 @@ import org.apache.poi.hssf.record.aggreg
 import org.apache.poi.hssf.record.cf.TestCellRange;
 import org.apache.poi.hssf.record.chart.AllChartRecordTests;
 import org.apache.poi.hssf.record.common.TestUnicodeString;
-import org.apache.poi.hssf.record.crypto.AllHSSFEncryptionTests;
 import org.apache.poi.hssf.record.pivot.AllPivotRecordTests;
+import org.apache.poi.poifs.crypt.AllEncryptionTests;
 import org.apache.poi.ss.formula.constant.TestConstantValueParser;
 import org.apache.poi.ss.formula.ptg.AllFormulaTests;
 import org.junit.runner.RunWith;
@@ -34,7 +34,7 @@ import org.junit.runners.Suite;
 @RunWith(Suite.class)
 @Suite.SuiteClasses({
     AllChartRecordTests.class,
-    AllHSSFEncryptionTests.class,
+    AllEncryptionTests.class,
     AllFormulaTests.class,
     AllPivotRecordTests.class,
     AllRecordAggregateTests.class,

Modified: poi/trunk/src/testcases/org/apache/poi/hssf/record/TestRecordFactoryInputStream.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/hssf/record/TestRecordFactoryInputStream.java?rev=1762726&r1=1762725&r2=1762726&view=diff
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/hssf/record/TestRecordFactoryInputStream.java (original)
+++ poi/trunk/src/testcases/org/apache/poi/hssf/record/TestRecordFactoryInputStream.java Wed Sep 28 23:36:09 2016
@@ -151,11 +151,12 @@ public final class TestRecordFactoryInpu
 	
 	
 	/**
-	 * makes sure the record stream starts with {@link BOFRecord} and then {@link WindowOneRecord}
-	 * The second record is gets decrypted so this method also checks its content.
+	 * makes sure the record stream starts with {@link BOFRecord}, {@link FilePassRecord} and then {@link WindowOneRecord}
+	 * The third record is decrypted so this method also checks its content.
 	 */
 	private void confirmReadInitialRecords(RecordFactoryInputStream rfis) {
 		assertEquals(BOFRecord.class, rfis.nextRecord().getClass());
+		FilePassRecord recFP = (FilePassRecord) rfis.nextRecord();
 		WindowOneRecord rec1 = (WindowOneRecord) rfis.nextRecord();
 		assertArrayEquals(HexRead.readFromString(SAMPLE_WINDOW1),rec1.serialize());
 	}

Modified: poi/trunk/src/testcases/org/apache/poi/poifs/crypt/TestCipherAlgorithm.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/poifs/crypt/TestCipherAlgorithm.java?rev=1762726&r1=1762725&r2=1762726&view=diff
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/poifs/crypt/TestCipherAlgorithm.java (original)
+++ poi/trunk/src/testcases/org/apache/poi/poifs/crypt/TestCipherAlgorithm.java Wed Sep 28 23:36:09 2016
@@ -17,14 +17,14 @@
 
 package org.apache.poi.poifs.crypt;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
 
 import org.apache.poi.EncryptedDocumentException;
 import org.junit.Test;
 
 public class TestCipherAlgorithm {
     @Test
-    public void test() {
+    public void validInputs() {
         assertEquals(128, CipherAlgorithm.aes128.defaultKeySize);
         
         for(CipherAlgorithm alg : CipherAlgorithm.values()) {
@@ -33,27 +33,20 @@ public class TestCipherAlgorithm {
 
         assertEquals(CipherAlgorithm.aes128, CipherAlgorithm.fromEcmaId(0x660E));
         assertEquals(CipherAlgorithm.aes192, CipherAlgorithm.fromXmlId("AES", 192));
-        
-        try {
-            CipherAlgorithm.fromEcmaId(0);
-            fail("Should throw exception");
-        } catch (EncryptedDocumentException e) {
-            // expected
-        }
-
-        try {
-            CipherAlgorithm.fromXmlId("AES", 1);
-            fail("Should throw exception");
-        } catch (EncryptedDocumentException e) {
-            // expected
-        }
-
-        try {
-            CipherAlgorithm.fromXmlId("RC1", 0x40);
-            fail("Should throw exception");
-        } catch (EncryptedDocumentException e) {
-            // expected
-        }
     }
-
+    
+    @Test(expected=EncryptedDocumentException.class)
+    public void invalidEcmaId() {
+        CipherAlgorithm.fromEcmaId(0);
+    }
+    
+    @Test(expected=EncryptedDocumentException.class)
+    public void invalidXmlId1() {
+        CipherAlgorithm.fromXmlId("AES", 1);
+    }
+    
+    @Test(expected=EncryptedDocumentException.class)
+    public void invalidXmlId2() {
+        CipherAlgorithm.fromXmlId("RC1", 0x40);
+    }
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org