poi-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From kiwiwi...@apache.org
Subject svn commit: r1762726 [2/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...
Date Wed, 28 Sep 2016 23:36:09 GMT
Modified: poi/trunk/src/java/org/apache/poi/poifs/crypt/EncryptionHeader.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/poifs/crypt/EncryptionHeader.java?rev=1762726&r1=1762725&r2=1762726&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/poifs/crypt/EncryptionHeader.java (original)
+++ poi/trunk/src/java/org/apache/poi/poifs/crypt/EncryptionHeader.java Wed Sep 28 23:36:09 2016
@@ -16,12 +16,11 @@
 ==================================================================== */
 package org.apache.poi.poifs.crypt;
 
-
 /**
  * Reads and processes OOXML Encryption Headers
  * The constants are largely based on ZIP constants.
  */
-public abstract class EncryptionHeader {
+public abstract class EncryptionHeader implements Cloneable {
     public static final int ALGORITHM_RC4 = CipherAlgorithm.rc4.ecmaId;
     public static final int ALGORITHM_AES_128 = CipherAlgorithm.aes128.ecmaId;
     public static final int ALGORITHM_AES_192 = CipherAlgorithm.aes192.ecmaId;
@@ -132,4 +131,11 @@ public abstract class EncryptionHeader {
     protected void setCspName(String cspName) {
         this.cspName = cspName;
     }
+
+    @Override
+    public EncryptionHeader clone() throws CloneNotSupportedException {
+        EncryptionHeader other = (EncryptionHeader)super.clone();
+        other.keySalt = (keySalt == null) ? null : keySalt.clone();
+        return other;
+    }
 }

Modified: poi/trunk/src/java/org/apache/poi/poifs/crypt/EncryptionInfo.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/poifs/crypt/EncryptionInfo.java?rev=1762726&r1=1762725&r2=1762726&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/poifs/crypt/EncryptionInfo.java (original)
+++ poi/trunk/src/java/org/apache/poi/poifs/crypt/EncryptionInfo.java Wed Sep 28 23:36:09 2016
@@ -20,6 +20,7 @@ import static org.apache.poi.poifs.crypt
 import static org.apache.poi.poifs.crypt.EncryptionMode.binaryRC4;
 import static org.apache.poi.poifs.crypt.EncryptionMode.cryptoAPI;
 import static org.apache.poi.poifs.crypt.EncryptionMode.standard;
+import static org.apache.poi.poifs.crypt.EncryptionMode.xor;
 
 import java.io.IOException;
 
@@ -34,15 +35,16 @@ import org.apache.poi.util.LittleEndianI
 
 /**
  */
-public class EncryptionInfo {
+public class EncryptionInfo implements Cloneable {
+    private final EncryptionMode encryptionMode;
     private final int versionMajor;
     private final int versionMinor;
     private final int encryptionFlags;
     
-    private final EncryptionHeader header;
-    private final EncryptionVerifier verifier;
-    private final Decryptor decryptor;
-    private final Encryptor encryptor;
+    private EncryptionHeader header;
+    private EncryptionVerifier verifier;
+    private Decryptor decryptor;
+    private Encryptor encryptor;
 
     /**
      * A flag that specifies whether CryptoAPI RC4 or ECMA-376 encryption
@@ -75,50 +77,55 @@ public class EncryptionInfo {
     public EncryptionInfo(POIFSFileSystem fs) throws IOException {
        this(fs.getRoot());
     }
+    
     /**
      * Opens for decryption
      */
     public EncryptionInfo(OPOIFSFileSystem fs) throws IOException {
        this(fs.getRoot());
     }
+    
     /**
      * Opens for decryption
      */
     public EncryptionInfo(NPOIFSFileSystem fs) throws IOException {
        this(fs.getRoot());
     }
+    
     /**
      * Opens for decryption
      */
     public EncryptionInfo(DirectoryNode dir) throws IOException {
-        this(dir.createDocumentInputStream("EncryptionInfo"), false);
+        this(dir.createDocumentInputStream("EncryptionInfo"), null);
     }
 
-    public EncryptionInfo(LittleEndianInput dis, boolean isCryptoAPI) throws IOException {
-        final EncryptionMode encryptionMode;
-        versionMajor = dis.readShort();
-        versionMinor = dis.readShort();
+    public EncryptionInfo(LittleEndianInput dis, EncryptionMode preferredEncryptionMode) throws IOException {
+        if (preferredEncryptionMode == xor) {
+            versionMajor = xor.versionMajor;
+            versionMinor = xor.versionMinor;
+        } else {
+            versionMajor = dis.readUShort();
+            versionMinor = dis.readUShort();
+        }
 
-        if (!isCryptoAPI
-            && versionMajor == binaryRC4.versionMajor
+        if (   versionMajor == xor.versionMajor
+            && versionMinor == xor.versionMinor) {
+            encryptionMode = xor;
+            encryptionFlags = -1;
+        } else if (   versionMajor == binaryRC4.versionMajor
             && versionMinor == binaryRC4.versionMinor) {
             encryptionMode = binaryRC4;
             encryptionFlags = -1;
-        } else if (!isCryptoAPI
-            && versionMajor == agile.versionMajor
+        } else if (
+               2 <= versionMajor && versionMajor <= 4
+            && versionMinor == 2) {
+            encryptionMode = (preferredEncryptionMode == cryptoAPI) ? cryptoAPI : standard;
+            encryptionFlags = dis.readInt();
+        } else if (
+               versionMajor == agile.versionMajor
             && versionMinor == agile.versionMinor){
             encryptionMode = agile;
             encryptionFlags = dis.readInt();
-        } else if (!isCryptoAPI
-            && 2 <= versionMajor && versionMajor <= 4
-            && versionMinor == standard.versionMinor) {
-            encryptionMode = standard;
-            encryptionFlags = dis.readInt();
-        } else if (isCryptoAPI
-            && 2 <= versionMajor && versionMajor <= 4
-            && versionMinor == cryptoAPI.versionMinor) {
-            encryptionMode = cryptoAPI;
-            encryptionFlags = dis.readInt();
         } else {
             encryptionFlags = dis.readInt();
             throw new EncryptedDocumentException(
@@ -138,10 +145,6 @@ public class EncryptionInfo {
         }
 
         eib.initialize(this, dis);
-        header = eib.getHeader();
-        verifier = eib.getVerifier();
-        decryptor = eib.getDecryptor();
-        encryptor = eib.getEncryptor();
     }
     
     /**
@@ -175,6 +178,7 @@ public class EncryptionInfo {
           , int blockSize
           , ChainingMode chainingMode
       ) {
+        this.encryptionMode = encryptionMode; 
         versionMajor = encryptionMode.versionMajor;
         versionMinor = encryptionMode.versionMinor;
         encryptionFlags = encryptionMode.encryptionFlags;
@@ -187,11 +191,6 @@ public class EncryptionInfo {
         }
         
         eib.initialize(this, cipherAlgorithm, hashAlgorithm, keyBits, blockSize, chainingMode);
-        
-        header = eib.getHeader();
-        verifier = eib.getVerifier();
-        decryptor = eib.getDecryptor();
-        encryptor = eib.getEncryptor();
     }
 
     protected static EncryptionInfoBuilder getBuilder(EncryptionMode encryptionMode)
@@ -229,4 +228,36 @@ public class EncryptionInfo {
     public Encryptor getEncryptor() {
         return encryptor;
     }
-}
+
+    public void setHeader(EncryptionHeader header) {
+        this.header = header;
+    }
+
+    public void setVerifier(EncryptionVerifier verifier) {
+        this.verifier = verifier;
+    }
+
+    public void setDecryptor(Decryptor decryptor) {
+        this.decryptor = decryptor;
+    }
+
+    public void setEncryptor(Encryptor encryptor) {
+        this.encryptor = encryptor;
+    }
+
+    public EncryptionMode getEncryptionMode() {
+        return encryptionMode;
+    }
+    
+    @Override
+    public EncryptionInfo clone() throws CloneNotSupportedException {
+        EncryptionInfo other = (EncryptionInfo)super.clone();
+        other.header = header.clone();
+        other.verifier = verifier.clone();
+        other.decryptor = decryptor.clone();
+        other.decryptor.setEncryptionInfo(other);
+        other.encryptor = encryptor.clone();
+        other.encryptor.setEncryptionInfo(other);
+        return other;
+    }
+}
\ No newline at end of file

Modified: poi/trunk/src/java/org/apache/poi/poifs/crypt/EncryptionInfoBuilder.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/poifs/crypt/EncryptionInfoBuilder.java?rev=1762726&r1=1762725&r2=1762726&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/poifs/crypt/EncryptionInfoBuilder.java (original)
+++ poi/trunk/src/java/org/apache/poi/poifs/crypt/EncryptionInfoBuilder.java Wed Sep 28 23:36:09 2016
@@ -30,24 +30,4 @@ public interface EncryptionInfoBuilder {
      * initialize the builder from scratch
      */
     void initialize(EncryptionInfo ei, CipherAlgorithm cipherAlgorithm, HashAlgorithm hashAlgorithm, int keyBits, int blockSize, ChainingMode chainingMode);
-
-    /**
-     * @return the header data
-     */
-    EncryptionHeader getHeader();
-
-    /**
-     * @return the verifier data
-     */
-    EncryptionVerifier getVerifier();
-
-    /**
-     * @return the decryptor
-     */
-    Decryptor getDecryptor();
-
-    /**
-     * @return the encryptor
-     */
-    Encryptor getEncryptor();
 }

Modified: poi/trunk/src/java/org/apache/poi/poifs/crypt/EncryptionMode.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/poifs/crypt/EncryptionMode.java?rev=1762726&r1=1762725&r2=1762726&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/poifs/crypt/EncryptionMode.java (original)
+++ poi/trunk/src/java/org/apache/poi/poifs/crypt/EncryptionMode.java Wed Sep 28 23:36:09 2016
@@ -33,7 +33,9 @@ public enum EncryptionMode {
     /* @see <a href="http://msdn.microsoft.com/en-us/library/dd906097(v=office.12).aspx">2.3.4.5 \EncryptionInfo Stream (Standard Encryption)</a> */
     standard("org.apache.poi.poifs.crypt.standard.StandardEncryptionInfoBuilder", 4, 2, 0x24),
     /* @see <a href="http://msdn.microsoft.com/en-us/library/dd925810(v=office.12).aspx">2.3.4.10 \EncryptionInfo Stream (Agile Encryption)</a> */
-    agile("org.apache.poi.poifs.crypt.agile.AgileEncryptionInfoBuilder", 4, 4, 0x40)
+    agile("org.apache.poi.poifs.crypt.agile.AgileEncryptionInfoBuilder", 4, 4, 0x40),
+    /* @see <a href="https://msdn.microsoft.com/en-us/library/dd907599(v=office.12).aspx">XOR Obfuscation</a> */
+    xor("org.apache.poi.poifs.crypt.xor.XOREncryptionInfoBuilder", 0, 0, 0)
     ;
     
     public final String builder;

Modified: poi/trunk/src/java/org/apache/poi/poifs/crypt/EncryptionVerifier.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/poifs/crypt/EncryptionVerifier.java?rev=1762726&r1=1762725&r2=1762726&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/poifs/crypt/EncryptionVerifier.java (original)
+++ poi/trunk/src/java/org/apache/poi/poifs/crypt/EncryptionVerifier.java Wed Sep 28 23:36:09 2016
@@ -16,11 +16,10 @@
 ==================================================================== */
 package org.apache.poi.poifs.crypt;
 
-
 /**
  * Used when checking if a key is valid for a document 
  */
-public abstract class EncryptionVerifier {
+public abstract class EncryptionVerifier implements Cloneable {
     private byte[] salt;
     private byte[] encryptedVerifier;
     private byte[] encryptedVerifierHash;
@@ -105,5 +104,13 @@ public abstract class EncryptionVerifier
         this.hashAlgorithm = hashAlgorithm;
     }
     
-    
+    @Override
+    public EncryptionVerifier clone() throws CloneNotSupportedException {
+        EncryptionVerifier other = (EncryptionVerifier)super.clone();
+        other.salt = (salt == null) ? null : salt.clone();
+        other.encryptedVerifier = (encryptedVerifier == null) ? null : encryptedVerifier.clone();
+        other.encryptedVerifierHash = (encryptedVerifierHash == null) ? null : encryptedVerifierHash.clone();
+        other.encryptedKey = (encryptedKey == null) ? null : encryptedKey.clone();
+        return other;
+    }
 }

Modified: poi/trunk/src/java/org/apache/poi/poifs/crypt/Encryptor.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/poifs/crypt/Encryptor.java?rev=1762726&r1=1762725&r2=1762726&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/poifs/crypt/Encryptor.java (original)
+++ poi/trunk/src/java/org/apache/poi/poifs/crypt/Encryptor.java Wed Sep 28 23:36:09 2016
@@ -21,14 +21,16 @@ import java.io.OutputStream;
 import java.security.GeneralSecurityException;
 
 import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
 
 import org.apache.poi.poifs.filesystem.DirectoryNode;
 import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
 import org.apache.poi.poifs.filesystem.OPOIFSFileSystem;
 import org.apache.poi.poifs.filesystem.POIFSFileSystem;
 
-public abstract class Encryptor {
+public abstract class Encryptor implements Cloneable {
     protected static final String DEFAULT_POIFS_ENTRY = Decryptor.DEFAULT_POIFS_ENTRY;
+    private EncryptionInfo encryptionInfo;
     private SecretKey secretKey;
     
     /**
@@ -59,11 +61,43 @@ public abstract class Encryptor {
         return getDataStream(fs.getRoot());
     }
 
+    public ChunkedCipherOutputStream getDataStream(OutputStream stream, int initialOffset)
+    throws IOException, GeneralSecurityException {
+        throw new RuntimeException("this decryptor doesn't support writing directly to a stream");
+    }
+    
     public SecretKey getSecretKey() {
         return secretKey;
     }
 
-    protected void setSecretKey(SecretKey secretKey) {
+    public void setSecretKey(SecretKey secretKey) {
         this.secretKey = secretKey;
     }
+
+    public EncryptionInfo getEncryptionInfo() {
+        return encryptionInfo;
+    }
+
+    public void setEncryptionInfo(EncryptionInfo encryptionInfo) {
+        this.encryptionInfo = encryptionInfo;
+    }
+
+    /**
+     * Sets the chunk size of the data stream.
+     * Needs to be set before the data stream is requested.
+     * When not set, the implementation uses method specific default values
+     *
+     * @param chunkSize the chunk size, i.e. the block size with the same encryption key
+     */
+    public void setChunkSize(int chunkSize) {
+        throw new RuntimeException("this decryptor doesn't support changing the chunk size");
+    }
+    
+    @Override
+    public Encryptor clone() throws CloneNotSupportedException {
+        Encryptor other = (Encryptor)super.clone();
+        other.secretKey = new SecretKeySpec(secretKey.getEncoded(), secretKey.getAlgorithm());
+        // encryptionInfo is set from outside
+        return other;
+    }
 }

Modified: poi/trunk/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4Decryptor.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4Decryptor.java?rev=1762726&r1=1762725&r2=1762726&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4Decryptor.java (original)
+++ poi/trunk/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4Decryptor.java Wed Sep 28 23:36:09 2016
@@ -34,31 +34,38 @@ import org.apache.poi.poifs.filesystem.D
 import org.apache.poi.util.LittleEndian;
 import org.apache.poi.util.StringUtil;
 
-public class BinaryRC4Decryptor extends Decryptor {
+public class BinaryRC4Decryptor extends Decryptor implements Cloneable {
     private long _length = -1L;
+    private int _chunkSize = 512;
     
     private class BinaryRC4CipherInputStream extends ChunkedCipherInputStream {
 
+        @Override
         protected Cipher initCipherForBlock(Cipher existing, int block)
                 throws GeneralSecurityException {
-            return BinaryRC4Decryptor.initCipherForBlock(existing, block, builder, getSecretKey(), Cipher.DECRYPT_MODE);
+            return BinaryRC4Decryptor.this.initCipherForBlock(existing, block);
         }
 
         public BinaryRC4CipherInputStream(DocumentInputStream stream, long size)
                 throws GeneralSecurityException {
-            super(stream, size, 512);
+            super(stream, size, _chunkSize);
         }
+
+        public BinaryRC4CipherInputStream(InputStream stream)
+                throws GeneralSecurityException {
+            super(stream, Integer.MAX_VALUE, _chunkSize);
+        }    
     }
 
-    protected BinaryRC4Decryptor(BinaryRC4EncryptionInfoBuilder builder) {
-        super(builder);
+    protected BinaryRC4Decryptor() {
     }
 
+    @Override
     public boolean verifyPassword(String password) {
-        EncryptionVerifier ver = builder.getVerifier();
+        EncryptionVerifier ver = getEncryptionInfo().getVerifier();
         SecretKey skey = generateSecretKey(password, ver);
         try {
-            Cipher cipher = initCipherForBlock(null, 0, builder, skey, Cipher.DECRYPT_MODE);
+            Cipher cipher = initCipherForBlock(null, 0, getEncryptionInfo(), skey, Cipher.DECRYPT_MODE);
             byte encryptedVerifier[] = ver.getEncryptedVerifier();
             byte verifier[] = new byte[encryptedVerifier.length];
             cipher.update(encryptedVerifier, 0, encryptedVerifier.length, verifier);
@@ -78,17 +85,23 @@ public class BinaryRC4Decryptor extends
         return false;
     }
 
+    @Override
+    public Cipher initCipherForBlock(Cipher cipher, int block)
+    throws GeneralSecurityException {
+        return initCipherForBlock(cipher, block, getEncryptionInfo(), getSecretKey(), Cipher.DECRYPT_MODE);
+    }    
+    
     protected static Cipher initCipherForBlock(Cipher cipher, int block,
-        EncryptionInfoBuilder builder, SecretKey skey, int encryptMode)
+        EncryptionInfo encryptionInfo, SecretKey skey, int encryptMode)
     throws GeneralSecurityException {
-        EncryptionVerifier ver = builder.getVerifier();
+        EncryptionVerifier ver = encryptionInfo.getVerifier();
         HashAlgorithm hashAlgo = ver.getHashAlgorithm();
         byte blockKey[] = new byte[4];
         LittleEndian.putUInt(blockKey, 0, block);
         byte encKey[] = CryptoFunctions.generateKey(skey.getEncoded(), hashAlgo, blockKey, 16);
         SecretKey key = new SecretKeySpec(encKey, skey.getAlgorithm());
         if (cipher == null) {
-            EncryptionHeader em = builder.getHeader();
+            EncryptionHeader em = encryptionInfo.getHeader();
             cipher = CryptoFunctions.getCipher(key, em.getCipherAlgorithm(), null, null, encryptMode);
         } else {
             cipher.init(encryptMode, key);
@@ -96,10 +109,10 @@ public class BinaryRC4Decryptor extends
         return cipher;
     }
 
-    protected static SecretKey generateSecretKey(String password,
-            EncryptionVerifier ver) {
-        if (password.length() > 255)
+    protected static SecretKey generateSecretKey(String password, EncryptionVerifier ver) {
+        if (password.length() > 255) {
             password = password.substring(0, 255);
+        }
         HashAlgorithm hashAlgo = ver.getHashAlgorithm();
         MessageDigest hashAlg = CryptoFunctions.getMessageDigest(hashAlgo);
         byte hash[] = hashAlg.digest(StringUtil.getToUnicodeLE(password));
@@ -116,15 +129,23 @@ public class BinaryRC4Decryptor extends
         return skey;
     }
 
+    @Override
     @SuppressWarnings("resource")
-    public InputStream getDataStream(DirectoryNode dir) throws IOException,
+    public ChunkedCipherInputStream getDataStream(DirectoryNode dir) throws IOException,
             GeneralSecurityException {
         DocumentInputStream dis = dir.createDocumentInputStream(DEFAULT_POIFS_ENTRY);
         _length = dis.readLong();
-        BinaryRC4CipherInputStream cipherStream = new BinaryRC4CipherInputStream(dis, _length);
-        return cipherStream;
+        return new BinaryRC4CipherInputStream(dis, _length);
+    }
+    
+    @Override
+    public InputStream getDataStream(InputStream stream, int size, int initialPos)
+            throws IOException, GeneralSecurityException {
+        return new BinaryRC4CipherInputStream(stream);
     }
+    
 
+    @Override
     public long getLength() {
         if (_length == -1L) {
             throw new IllegalStateException("Decryptor.getDataStream() was not called");
@@ -132,4 +153,14 @@ public class BinaryRC4Decryptor extends
         
         return _length;
     }
+
+    @Override
+    public void setChunkSize(int chunkSize) {
+        _chunkSize = chunkSize;
+    }
+    
+    @Override
+    public BinaryRC4Decryptor clone() throws CloneNotSupportedException {
+        return (BinaryRC4Decryptor)super.clone();
+    }
 }

Modified: poi/trunk/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4EncryptionHeader.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4EncryptionHeader.java?rev=1762726&r1=1762725&r2=1762726&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4EncryptionHeader.java (original)
+++ poi/trunk/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4EncryptionHeader.java Wed Sep 28 23:36:09 2016
@@ -24,8 +24,7 @@ import org.apache.poi.poifs.crypt.HashAl
 import org.apache.poi.poifs.crypt.standard.EncryptionRecord;
 import org.apache.poi.util.LittleEndianByteArrayOutputStream;
 
-public class BinaryRC4EncryptionHeader extends EncryptionHeader implements
-        EncryptionRecord {
+public class BinaryRC4EncryptionHeader extends EncryptionHeader implements EncryptionRecord, Cloneable {
 
     protected BinaryRC4EncryptionHeader() {
         setCipherAlgorithm(CipherAlgorithm.rc4);
@@ -39,6 +38,14 @@ public class BinaryRC4EncryptionHeader e
         setChainingMode(null);
     }
 
+    @Override
     public void write(LittleEndianByteArrayOutputStream littleendianbytearrayoutputstream) {
     }
+
+    @Override
+    public BinaryRC4EncryptionHeader clone() throws CloneNotSupportedException {
+        return (BinaryRC4EncryptionHeader)super.clone();
+    }
+    
+    
 }

Modified: poi/trunk/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4EncryptionInfoBuilder.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4EncryptionInfoBuilder.java?rev=1762726&r1=1762725&r2=1762726&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4EncryptionInfoBuilder.java (original)
+++ poi/trunk/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4EncryptionInfoBuilder.java Wed Sep 28 23:36:09 2016
@@ -23,55 +23,37 @@ import org.apache.poi.util.LittleEndianI
 
 public class BinaryRC4EncryptionInfoBuilder implements EncryptionInfoBuilder {
 
-    EncryptionInfo info;
-    BinaryRC4EncryptionHeader header;
-    BinaryRC4EncryptionVerifier verifier;
-    BinaryRC4Decryptor decryptor;
-    BinaryRC4Encryptor encryptor;
-
     public BinaryRC4EncryptionInfoBuilder() {
     }
 
+    @Override
     public void initialize(EncryptionInfo info, LittleEndianInput dis)
     throws IOException {
-        this.info = info;
         int vMajor = info.getVersionMajor();
         int vMinor = info.getVersionMinor();
         assert (vMajor == 1 && vMinor == 1);
 
-        header = new BinaryRC4EncryptionHeader();
-        verifier = new BinaryRC4EncryptionVerifier(dis);
-        decryptor = new BinaryRC4Decryptor(this);
-        encryptor = new BinaryRC4Encryptor(this);
+        info.setHeader(new BinaryRC4EncryptionHeader());
+        info.setVerifier(new BinaryRC4EncryptionVerifier(dis));
+        Decryptor dec = new BinaryRC4Decryptor();
+        dec.setEncryptionInfo(info);
+        info.setDecryptor(dec);
+        Encryptor enc = new BinaryRC4Encryptor();
+        enc.setEncryptionInfo(info);
+        info.setEncryptor(enc);
     }
 
+    @Override
     public void initialize(EncryptionInfo info,
         CipherAlgorithm cipherAlgorithm, HashAlgorithm hashAlgorithm,
         int keyBits, int blockSize, ChainingMode chainingMode) {
-        this.info = info;
-        header = new BinaryRC4EncryptionHeader();
-        verifier = new BinaryRC4EncryptionVerifier();
-        decryptor = new BinaryRC4Decryptor(this);
-        encryptor = new BinaryRC4Encryptor(this);
-    }
-
-    public BinaryRC4EncryptionHeader getHeader() {
-        return header;
-    }
-
-    public BinaryRC4EncryptionVerifier getVerifier() {
-        return verifier;
-    }
-
-    public BinaryRC4Decryptor getDecryptor() {
-        return decryptor;
-    }
-
-    public BinaryRC4Encryptor getEncryptor() {
-        return encryptor;
-    }
-
-    public EncryptionInfo getEncryptionInfo() {
-        return info;
+        info.setHeader(new BinaryRC4EncryptionHeader());
+        info.setVerifier(new BinaryRC4EncryptionVerifier());
+        Decryptor dec = new BinaryRC4Decryptor();
+        dec.setEncryptionInfo(info);
+        info.setDecryptor(dec);
+        Encryptor enc = new BinaryRC4Encryptor();
+        enc.setEncryptionInfo(info);
+        info.setEncryptor(enc);
     }
 }

Modified: poi/trunk/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4EncryptionVerifier.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4EncryptionVerifier.java?rev=1762726&r1=1762725&r2=1762726&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4EncryptionVerifier.java (original)
+++ poi/trunk/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4EncryptionVerifier.java Wed Sep 28 23:36:09 2016
@@ -23,7 +23,7 @@ import org.apache.poi.poifs.crypt.standa
 import org.apache.poi.util.LittleEndianByteArrayOutputStream;
 import org.apache.poi.util.LittleEndianInput;
 
-public class BinaryRC4EncryptionVerifier extends EncryptionVerifier implements EncryptionRecord {
+public class BinaryRC4EncryptionVerifier extends EncryptionVerifier implements EncryptionRecord, Cloneable {
 
     protected BinaryRC4EncryptionVerifier() {
         setSpinCount(-1);
@@ -50,6 +50,7 @@ public class BinaryRC4EncryptionVerifier
         setHashAlgorithm(HashAlgorithm.md5);
     }
 
+    @Override
     protected void setSalt(byte salt[]) {
         if (salt == null || salt.length != 16) {
             throw new EncryptedDocumentException("invalid verifier salt");
@@ -58,14 +59,17 @@ public class BinaryRC4EncryptionVerifier
         super.setSalt(salt);
     }
 
+    @Override
     protected void setEncryptedVerifier(byte encryptedVerifier[]) {
         super.setEncryptedVerifier(encryptedVerifier);
     }
 
+    @Override
     protected void setEncryptedVerifierHash(byte encryptedVerifierHash[]) {
         super.setEncryptedVerifierHash(encryptedVerifierHash);
     }
 
+    @Override
     public void write(LittleEndianByteArrayOutputStream bos) {
         byte salt[] = getSalt();
         assert (salt.length == 16);
@@ -78,4 +82,8 @@ public class BinaryRC4EncryptionVerifier
         bos.write(encryptedVerifierHash);
     }
 
+    @Override
+    public BinaryRC4EncryptionVerifier clone() throws CloneNotSupportedException {
+        return (BinaryRC4EncryptionVerifier)super.clone();
+    }
 }

Modified: poi/trunk/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4Encryptor.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4Encryptor.java?rev=1762726&r1=1762725&r2=1762726&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4Encryptor.java (original)
+++ poi/trunk/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4Encryptor.java Wed Sep 28 23:36:09 2016
@@ -34,39 +34,19 @@ import org.apache.poi.poifs.crypt.Crypto
 import org.apache.poi.poifs.crypt.DataSpaceMapUtils;
 import org.apache.poi.poifs.crypt.EncryptionInfo;
 import org.apache.poi.poifs.crypt.Encryptor;
+import org.apache.poi.poifs.crypt.HashAlgorithm;
 import org.apache.poi.poifs.crypt.standard.EncryptionRecord;
 import org.apache.poi.poifs.filesystem.DirectoryNode;
 import org.apache.poi.util.LittleEndianByteArrayOutputStream;
 
-public class BinaryRC4Encryptor extends Encryptor {
+public class BinaryRC4Encryptor extends Encryptor implements Cloneable {
 
-    private final BinaryRC4EncryptionInfoBuilder builder;
+    private int _chunkSize = 512;
     
-    protected class BinaryRC4CipherOutputStream extends ChunkedCipherOutputStream {
-
-        protected Cipher initCipherForBlock(Cipher cipher, int block, boolean lastChunk)
-        throws GeneralSecurityException {
-            return BinaryRC4Decryptor.initCipherForBlock(cipher, block, builder, getSecretKey(), Cipher.ENCRYPT_MODE);
-        }
-
-        protected void calculateChecksum(File file, int i) {
-        }
-
-        protected void createEncryptionInfoEntry(DirectoryNode dir, File tmpFile)
-        throws IOException, GeneralSecurityException {
-            BinaryRC4Encryptor.this.createEncryptionInfoEntry(dir);
-        }
-
-        public BinaryRC4CipherOutputStream(DirectoryNode dir)
-        throws IOException, GeneralSecurityException {
-            super(dir, 512);
-        }
-    }
-
-    protected BinaryRC4Encryptor(BinaryRC4EncryptionInfoBuilder builder) {
-        this.builder = builder;
+    protected BinaryRC4Encryptor() {
     }
 
+    @Override
     public void confirmPassword(String password) {
         Random r = new SecureRandom();
         byte salt[] = new byte[16];
@@ -76,20 +56,20 @@ public class BinaryRC4Encryptor extends
         confirmPassword(password, null, null, verifier, salt, null);
     }
 
+    @Override
     public void confirmPassword(String password, byte keySpec[],
             byte keySalt[], byte verifier[], byte verifierSalt[],
             byte integritySalt[]) {
-        BinaryRC4EncryptionVerifier ver = builder.getVerifier();
+        BinaryRC4EncryptionVerifier ver = (BinaryRC4EncryptionVerifier)getEncryptionInfo().getVerifier();
         ver.setSalt(verifierSalt);
         SecretKey skey = BinaryRC4Decryptor.generateSecretKey(password, ver);
         setSecretKey(skey);
         try {
-            Cipher cipher = BinaryRC4Decryptor.initCipherForBlock(null, 0, builder, skey, Cipher.ENCRYPT_MODE);
+            Cipher cipher = BinaryRC4Decryptor.initCipherForBlock(null, 0, getEncryptionInfo(), skey, Cipher.ENCRYPT_MODE);
             byte encryptedVerifier[] = new byte[16];
             cipher.update(verifier, 0, 16, encryptedVerifier);
             ver.setEncryptedVerifier(encryptedVerifier);
-            org.apache.poi.poifs.crypt.HashAlgorithm hashAlgo = ver
-                    .getHashAlgorithm();
+            HashAlgorithm hashAlgo = ver.getHashAlgorithm();
             MessageDigest hashAlg = CryptoFunctions.getMessageDigest(hashAlgo);
             byte calcVerifierHash[] = hashAlg.digest(verifier);
             byte encryptedVerifierHash[] = cipher.doFinal(calcVerifierHash);
@@ -99,22 +79,30 @@ public class BinaryRC4Encryptor extends
         }
     }
 
+    @Override
     public OutputStream getDataStream(DirectoryNode dir)
     throws IOException, GeneralSecurityException {
         OutputStream countStream = new BinaryRC4CipherOutputStream(dir);
         return countStream;
     }
 
+    @Override
+    public BinaryRC4CipherOutputStream getDataStream(OutputStream stream, int initialOffset)
+    throws IOException, GeneralSecurityException {
+        return new BinaryRC4CipherOutputStream(stream);
+    }
+    
     protected int getKeySizeInBytes() {
-        return builder.getHeader().getKeySize() / 8;
+        return getEncryptionInfo().getHeader().getKeySize() / 8;
     }
 
     protected void createEncryptionInfoEntry(DirectoryNode dir) throws IOException {
         DataSpaceMapUtils.addDefaultDataSpace(dir);
-        final EncryptionInfo info = builder.getEncryptionInfo();
-        final BinaryRC4EncryptionHeader header = builder.getHeader();
-        final BinaryRC4EncryptionVerifier verifier = builder.getVerifier();
+        final EncryptionInfo info = getEncryptionInfo();
+        final BinaryRC4EncryptionHeader header = (BinaryRC4EncryptionHeader)info.getHeader();
+        final BinaryRC4EncryptionVerifier verifier = (BinaryRC4EncryptionVerifier)info.getVerifier();
         EncryptionRecord er = new EncryptionRecord() {
+            @Override
             public void write(LittleEndianByteArrayOutputStream bos) {
                 bos.writeShort(info.getVersionMajor());
                 bos.writeShort(info.getVersionMinor());
@@ -124,4 +112,49 @@ public class BinaryRC4Encryptor extends
         };
         DataSpaceMapUtils.createEncryptionEntry(dir, "EncryptionInfo", er);
     }
+
+    @Override
+    public void setChunkSize(int chunkSize) {
+        _chunkSize = chunkSize;
+    }
+    
+    @Override
+    public BinaryRC4Encryptor clone() throws CloneNotSupportedException {
+        return (BinaryRC4Encryptor)super.clone();
+    }
+
+    protected class BinaryRC4CipherOutputStream extends ChunkedCipherOutputStream {
+
+        public BinaryRC4CipherOutputStream(OutputStream stream)
+        throws IOException, GeneralSecurityException {
+            super(stream, BinaryRC4Encryptor.this._chunkSize);
+        }
+
+        public BinaryRC4CipherOutputStream(DirectoryNode dir)
+        throws IOException, GeneralSecurityException {
+            super(dir, BinaryRC4Encryptor.this._chunkSize);
+        }
+
+        @Override
+        protected Cipher initCipherForBlock(Cipher cipher, int block, boolean lastChunk)
+        throws GeneralSecurityException {
+            return BinaryRC4Decryptor.initCipherForBlock(cipher, block, getEncryptionInfo(), getSecretKey(), Cipher.ENCRYPT_MODE);
+        }
+        
+        @Override
+        protected void calculateChecksum(File file, int i) {
+        }
+
+        @Override
+        protected void createEncryptionInfoEntry(DirectoryNode dir, File tmpFile)
+        throws IOException, GeneralSecurityException {
+            BinaryRC4Encryptor.this.createEncryptionInfoEntry(dir);
+        }
+
+        @Override
+        public void flush() throws IOException {
+            writeChunk(false);
+            super.flush();
+        }
+    }
 }

Modified: poi/trunk/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIDecryptor.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIDecryptor.java?rev=1762726&r1=1762725&r2=1762726&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIDecryptor.java (original)
+++ poi/trunk/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIDecryptor.java Wed Sep 28 23:36:09 2016
@@ -17,7 +17,6 @@
 
 package org.apache.poi.poifs.crypt.cryptoapi;
 
-import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
@@ -27,20 +26,20 @@ import java.util.Arrays;
 
 import javax.crypto.Cipher;
 import javax.crypto.SecretKey;
-import javax.crypto.ShortBufferException;
 import javax.crypto.spec.SecretKeySpec;
 
 import org.apache.poi.EncryptedDocumentException;
+import org.apache.poi.poifs.crypt.ChunkedCipherInputStream;
 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.filesystem.DirectoryNode;
 import org.apache.poi.poifs.filesystem.DocumentInputStream;
 import org.apache.poi.poifs.filesystem.DocumentNode;
-import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
+import org.apache.poi.poifs.filesystem.POIFSFileSystem;
 import org.apache.poi.util.BitField;
 import org.apache.poi.util.BitFieldFactory;
 import org.apache.poi.util.BoundedInputStream;
@@ -49,57 +48,11 @@ import org.apache.poi.util.LittleEndian;
 import org.apache.poi.util.LittleEndianInputStream;
 import org.apache.poi.util.StringUtil;
 
-public class CryptoAPIDecryptor extends Decryptor {
+public class CryptoAPIDecryptor extends Decryptor implements Cloneable {
 
     private long _length;
+    private int _chunkSize = -1;
     
-    private class SeekableByteArrayInputStream extends ByteArrayInputStream {
-        Cipher cipher;
-        byte oneByte[] = { 0 };
-        
-        public void seek(int newpos) {
-            if (newpos > count) {
-                throw new ArrayIndexOutOfBoundsException(newpos);
-            }
-            
-            this.pos = newpos;
-            mark = newpos;
-        }
-
-        public void setBlock(int block) throws GeneralSecurityException {
-            cipher = initCipherForBlock(cipher, block);
-        }
-
-        public synchronized int read() {
-            int ch = super.read();
-            if (ch == -1) return -1;
-            oneByte[0] = (byte) ch;
-            try {
-                cipher.update(oneByte, 0, 1, oneByte);
-            } catch (ShortBufferException e) {
-                throw new EncryptedDocumentException(e);
-            }
-            return oneByte[0];
-        }
-
-        public synchronized int read(byte b[], int off, int len) {
-            int readLen = super.read(b, off, len);
-            if (readLen ==-1) return -1;
-            try {
-                cipher.update(b, off, readLen, b, off);
-            } catch (ShortBufferException e) {
-                throw new EncryptedDocumentException(e);
-            }
-            return readLen;
-        }
-
-        public SeekableByteArrayInputStream(byte buf[])
-        throws GeneralSecurityException {
-            super(buf);
-            cipher = initCipherForBlock(null, 0);
-        }
-    }
-
     static class StreamDescriptorEntry {
         static BitField flagStream = BitFieldFactory.getInstance(1);
         
@@ -111,16 +64,16 @@ public class CryptoAPIDecryptor extends
         String streamName;
     }
 
-    protected CryptoAPIDecryptor(CryptoAPIEncryptionInfoBuilder builder) {
-        super(builder);
+    protected CryptoAPIDecryptor() {
         _length = -1L;
     }
 
+    @Override
     public boolean verifyPassword(String password) {
-        EncryptionVerifier ver = builder.getVerifier();
+        EncryptionVerifier ver = getEncryptionInfo().getVerifier();
         SecretKey skey = generateSecretKey(password, ver);
         try {
-            Cipher cipher = initCipherForBlock(null, 0, builder, skey, Cipher.DECRYPT_MODE);
+            Cipher cipher = initCipherForBlock(null, 0, getEncryptionInfo(), skey, Cipher.DECRYPT_MODE);
             byte encryptedVerifier[] = ver.getEncryptedVerifier();
             byte verifier[] = new byte[encryptedVerifier.length];
             cipher.update(encryptedVerifier, 0, encryptedVerifier.length, verifier);
@@ -140,30 +93,25 @@ public class CryptoAPIDecryptor extends
         return false;
     }
 
-    /**
-     * Initializes a cipher object for a given block index for decryption
-     *
-     * @param cipher may be null, otherwise the given instance is reset to the new block index
-     * @param block the block index, e.g. the persist/slide id (hslf)
-     * @return a new cipher object, if cipher was null, otherwise the reinitialized cipher
-     * @throws GeneralSecurityException
-     */
+    @Override
     public Cipher initCipherForBlock(Cipher cipher, int block)
     throws GeneralSecurityException {
-        return initCipherForBlock(cipher, block, builder, getSecretKey(), Cipher.DECRYPT_MODE);
+        EncryptionInfo ei = getEncryptionInfo();
+        SecretKey sk = getSecretKey();
+        return initCipherForBlock(cipher, block, ei, sk, Cipher.DECRYPT_MODE);
     }
 
     protected static Cipher initCipherForBlock(Cipher cipher, int block,
-        EncryptionInfoBuilder builder, SecretKey skey, int encryptMode)
+        EncryptionInfo encryptionInfo, SecretKey skey, int encryptMode)
     throws GeneralSecurityException {
-        EncryptionVerifier ver = builder.getVerifier();
+        EncryptionVerifier ver = encryptionInfo.getVerifier();
         HashAlgorithm hashAlgo = ver.getHashAlgorithm();
         byte blockKey[] = new byte[4];
         LittleEndian.putUInt(blockKey, 0, block);
         MessageDigest hashAlg = CryptoFunctions.getMessageDigest(hashAlgo);
         hashAlg.update(skey.getEncoded());
         byte encKey[] = hashAlg.digest(blockKey);
-        EncryptionHeader header = builder.getHeader();
+        EncryptionHeader header = encryptionInfo.getHeader();
         int keyBits = header.getKeySize();
         encKey = CryptoFunctions.getBlock0(encKey, keyBits / 8);
         if (keyBits == 40) {
@@ -190,6 +138,18 @@ public class CryptoAPIDecryptor extends
         return skey;
     }
 
+    @Override
+    public ChunkedCipherInputStream getDataStream(DirectoryNode dir)
+    throws IOException, GeneralSecurityException {
+        throw new IOException("not supported");
+    }
+
+    @Override
+    public ChunkedCipherInputStream getDataStream(InputStream stream, int size, int initialPos)
+            throws IOException, GeneralSecurityException {
+        return new CryptoAPICipherInputStream(stream, size, initialPos);
+    }
+    
     /**
      * Decrypt the Document-/SummaryInformation and other optionally streams.
      * Opposed to other crypto modes, cryptoapi is record based and can't be used
@@ -197,15 +157,17 @@ public class CryptoAPIDecryptor extends
      * 
      * @see <a href="http://msdn.microsoft.com/en-us/library/dd943321(v=office.12).aspx">2.3.5.4 RC4 CryptoAPI Encrypted Summary Stream</a>
      */
-    public InputStream getDataStream(DirectoryNode dir)
+    public POIFSFileSystem getSummaryEntries(DirectoryNode root, String encryptedStream)
     throws IOException, GeneralSecurityException {
-        NPOIFSFileSystem fsOut = new NPOIFSFileSystem();
-        DocumentNode es = (DocumentNode) dir.getEntry("EncryptedSummary");
-        DocumentInputStream dis = dir.createDocumentInputStream(es);
+        POIFSFileSystem fsOut = new POIFSFileSystem();
+        // HSLF: encryptedStream
+        // HSSF: encryption
+        DocumentNode es = (DocumentNode) root.getEntry(encryptedStream);
+        DocumentInputStream dis = root.createDocumentInputStream(es);
         ByteArrayOutputStream bos = new ByteArrayOutputStream();
         IOUtils.copy(dis, bos);
         dis.close();
-        SeekableByteArrayInputStream sbis = new SeekableByteArrayInputStream(bos.toByteArray());
+        CryptoAPIDocumentInputStream sbis = new CryptoAPIDocumentInputStream(this, bos.toByteArray());
         LittleEndianInputStream leis = new LittleEndianInputStream(sbis);
         int streamDescriptorArrayOffset = (int) leis.readUInt();
         /* int streamDescriptorArraySize = (int) */ leis.readUInt();
@@ -239,21 +201,40 @@ public class CryptoAPIDecryptor extends
         leis.close();
         sbis.close();
         sbis = null;
-        bos.reset();
-        fsOut.writeFilesystem(bos);
-        fsOut.close();
-        _length = bos.size();
-        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
-        return bis;
+        return fsOut;
     }
 
     /**
      * @return the length of the stream returned by {@link #getDataStream(DirectoryNode)}
      */
+    @Override
     public long getLength() {
         if (_length == -1L) {
             throw new IllegalStateException("Decryptor.getDataStream() was not called");
         }
         return _length;
     }
+
+    public void setChunkSize(int chunkSize) {
+        _chunkSize = chunkSize;
+    }
+    
+    @Override
+    public CryptoAPIDecryptor clone() throws CloneNotSupportedException {
+        return (CryptoAPIDecryptor)super.clone();
+    }
+
+    private class CryptoAPICipherInputStream extends ChunkedCipherInputStream {
+
+        @Override
+        protected Cipher initCipherForBlock(Cipher existing, int block)
+                throws GeneralSecurityException {
+            return CryptoAPIDecryptor.this.initCipherForBlock(existing, block);
+        }
+
+        public CryptoAPICipherInputStream(InputStream stream, long size, int initialPos)
+                throws GeneralSecurityException {
+            super(stream, size, _chunkSize, initialPos);
+        }    
+    }
 }

Modified: poi/trunk/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptionHeader.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptionHeader.java?rev=1762726&r1=1762725&r2=1762726&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptionHeader.java (original)
+++ poi/trunk/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptionHeader.java Wed Sep 28 23:36:09 2016
@@ -27,7 +27,7 @@ import org.apache.poi.poifs.crypt.HashAl
 import org.apache.poi.poifs.crypt.standard.StandardEncryptionHeader;
 import org.apache.poi.util.LittleEndianInput;
 
-public class CryptoAPIEncryptionHeader extends StandardEncryptionHeader {
+public class CryptoAPIEncryptionHeader extends StandardEncryptionHeader implements Cloneable {
 
     public CryptoAPIEncryptionHeader(LittleEndianInput is) throws IOException {
         super(is);
@@ -39,6 +39,7 @@ public class CryptoAPIEncryptionHeader e
         super(cipherAlgorithm, hashAlgorithm, keyBits, blockSize, chainingMode);
     }
 
+    @Override
     public void setKeySize(int keyBits) {
         // Microsoft Base Cryptographic Provider is limited up to 40 bits
         // http://msdn.microsoft.com/en-us/library/windows/desktop/aa375599(v=vs.85).aspx
@@ -59,4 +60,9 @@ public class CryptoAPIEncryptionHeader e
             setCspName(CipherProvider.rc4.cipherProviderName);
         }
     }
+
+    @Override
+    public CryptoAPIEncryptionHeader clone() throws CloneNotSupportedException {
+        return (CryptoAPIEncryptionHeader)super.clone();
+    }
 }

Modified: poi/trunk/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptionInfoBuilder.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptionInfoBuilder.java?rev=1762726&r1=1762725&r2=1762726&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptionInfoBuilder.java (original)
+++ poi/trunk/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptionInfoBuilder.java Wed Sep 28 23:36:09 2016
@@ -23,63 +23,52 @@ import org.apache.poi.poifs.crypt.*;
 import org.apache.poi.util.LittleEndianInput;
 
 public class CryptoAPIEncryptionInfoBuilder implements EncryptionInfoBuilder {
-    EncryptionInfo info;
-    CryptoAPIEncryptionHeader header;
-    CryptoAPIEncryptionVerifier verifier;
-    CryptoAPIDecryptor decryptor;
-    CryptoAPIEncryptor encryptor;
-
     public CryptoAPIEncryptionInfoBuilder() {
     }
 
     /**
      * initialize the builder from a stream
      */
+    @Override
     public void initialize(EncryptionInfo info, LittleEndianInput dis)
     throws IOException {
-        this.info = info;
         /* int hSize = */ dis.readInt();
-        header = new CryptoAPIEncryptionHeader(dis);
-        verifier = new CryptoAPIEncryptionVerifier(dis, header);
-        decryptor = new CryptoAPIDecryptor(this);
-        encryptor = new CryptoAPIEncryptor(this);
+        CryptoAPIEncryptionHeader header = new CryptoAPIEncryptionHeader(dis);
+        info.setHeader(header);
+        info.setVerifier(new CryptoAPIEncryptionVerifier(dis, header));
+        CryptoAPIDecryptor dec = new CryptoAPIDecryptor();
+        dec.setEncryptionInfo(info);
+        info.setDecryptor(dec);
+        CryptoAPIEncryptor enc = new CryptoAPIEncryptor();
+        enc.setEncryptionInfo(info);
+        info.setEncryptor(enc);
     }
 
     /**
      * initialize the builder from scratch
      */
+    @Override
     public void initialize(EncryptionInfo info,
             CipherAlgorithm cipherAlgorithm, HashAlgorithm hashAlgorithm,
             int keyBits, int blockSize, ChainingMode chainingMode) {
-        this.info = info;
-        if (cipherAlgorithm == null) cipherAlgorithm = CipherAlgorithm.rc4;
-        if (hashAlgorithm == null) hashAlgorithm = HashAlgorithm.sha1;
-        if (keyBits == -1) keyBits = 0x28; 
+        if (cipherAlgorithm == null) {
+            cipherAlgorithm = CipherAlgorithm.rc4;
+        }
+        if (hashAlgorithm == null) {
+            hashAlgorithm = HashAlgorithm.sha1;
+        }
+        if (keyBits == -1) {
+            keyBits = 0x28;
+        } 
         assert(cipherAlgorithm == CipherAlgorithm.rc4 && hashAlgorithm == HashAlgorithm.sha1);
         
-        header = new CryptoAPIEncryptionHeader(cipherAlgorithm, hashAlgorithm, keyBits, blockSize, chainingMode);
-        verifier = new CryptoAPIEncryptionVerifier(cipherAlgorithm, hashAlgorithm, keyBits, blockSize, chainingMode);
-        decryptor = new CryptoAPIDecryptor(this);
-        encryptor = new CryptoAPIEncryptor(this);
-    }
-
-    public CryptoAPIEncryptionHeader getHeader() {
-        return header;
-    }
-
-    public CryptoAPIEncryptionVerifier getVerifier() {
-        return verifier;
-    }
-
-    public CryptoAPIDecryptor getDecryptor() {
-        return decryptor;
-    }
-
-    public CryptoAPIEncryptor getEncryptor() {
-        return encryptor;
-    }
-
-    public EncryptionInfo getEncryptionInfo() {
-        return info;
+        info.setHeader(new CryptoAPIEncryptionHeader(cipherAlgorithm, hashAlgorithm, keyBits, blockSize, chainingMode));
+        info.setVerifier(new CryptoAPIEncryptionVerifier(cipherAlgorithm, hashAlgorithm, keyBits, blockSize, chainingMode));
+        CryptoAPIDecryptor dec = new CryptoAPIDecryptor();
+        dec.setEncryptionInfo(info);
+        info.setDecryptor(dec);
+        CryptoAPIEncryptor enc = new CryptoAPIEncryptor();
+        enc.setEncryptionInfo(info);
+        info.setEncryptor(enc);
     }
 }

Modified: poi/trunk/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptionVerifier.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptionVerifier.java?rev=1762726&r1=1762725&r2=1762726&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptionVerifier.java (original)
+++ poi/trunk/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptionVerifier.java Wed Sep 28 23:36:09 2016
@@ -23,7 +23,7 @@ import org.apache.poi.poifs.crypt.HashAl
 import org.apache.poi.poifs.crypt.standard.StandardEncryptionVerifier;
 import org.apache.poi.util.LittleEndianInput;
 
-public class CryptoAPIEncryptionVerifier extends StandardEncryptionVerifier {
+public class CryptoAPIEncryptionVerifier extends StandardEncryptionVerifier implements Cloneable {
 
     protected CryptoAPIEncryptionVerifier(LittleEndianInput is,
             CryptoAPIEncryptionHeader header) {
@@ -36,15 +36,23 @@ public class CryptoAPIEncryptionVerifier
         super(cipherAlgorithm, hashAlgorithm, keyBits, blockSize, chainingMode);
     }
 
+    @Override
     protected void setSalt(byte salt[]) {
         super.setSalt(salt);
     }
 
+    @Override
     protected void setEncryptedVerifier(byte encryptedVerifier[]) {
         super.setEncryptedVerifier(encryptedVerifier);
     }
 
+    @Override
     protected void setEncryptedVerifierHash(byte encryptedVerifierHash[]) {
         super.setEncryptedVerifierHash(encryptedVerifierHash);
     }
+
+    @Override
+    public CryptoAPIEncryptionVerifier clone() throws CloneNotSupportedException {
+        return (CryptoAPIEncryptionVerifier)super.clone();
+    }
 }

Modified: poi/trunk/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptor.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptor.java?rev=1762726&r1=1762725&r2=1762726&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptor.java (original)
+++ poi/trunk/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptor.java Wed Sep 28 23:36:09 2016
@@ -18,7 +18,7 @@
 package org.apache.poi.poifs.crypt.cryptoapi;
 
 import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
+import java.io.File;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.security.GeneralSecurityException;
@@ -36,6 +36,7 @@ import org.apache.poi.hpsf.DocumentSumma
 import org.apache.poi.hpsf.PropertySetFactory;
 import org.apache.poi.hpsf.SummaryInformation;
 import org.apache.poi.hpsf.WritingNotSupportedException;
+import org.apache.poi.poifs.crypt.ChunkedCipherOutputStream;
 import org.apache.poi.poifs.crypt.CryptoFunctions;
 import org.apache.poi.poifs.crypt.DataSpaceMapUtils;
 import org.apache.poi.poifs.crypt.EncryptionInfo;
@@ -50,13 +51,14 @@ import org.apache.poi.util.LittleEndian;
 import org.apache.poi.util.LittleEndianByteArrayOutputStream;
 import org.apache.poi.util.StringUtil;
 
-public class CryptoAPIEncryptor extends Encryptor {
-    private final CryptoAPIEncryptionInfoBuilder builder;
-
-    protected CryptoAPIEncryptor(CryptoAPIEncryptionInfoBuilder builder) {
-        this.builder = builder;
+public class CryptoAPIEncryptor extends Encryptor implements Cloneable {
+    
+    private int _chunkSize = 512;
+    
+    protected CryptoAPIEncryptor() {
     }
 
+    @Override
     public void confirmPassword(String password) {
         Random r = new SecureRandom();
         byte salt[] = new byte[16];
@@ -66,11 +68,12 @@ public class CryptoAPIEncryptor extends
         confirmPassword(password, null, null, verifier, salt, null);
     }
 
+    @Override
     public void confirmPassword(String password, byte keySpec[],
             byte keySalt[], byte verifier[], byte verifierSalt[],
             byte integritySalt[]) {
         assert(verifier != null && verifierSalt != null);
-        CryptoAPIEncryptionVerifier ver = builder.getVerifier();
+        CryptoAPIEncryptionVerifier ver = (CryptoAPIEncryptionVerifier)getEncryptionInfo().getVerifier();
         ver.setSalt(verifierSalt);
         SecretKey skey = CryptoAPIDecryptor.generateSecretKey(password, ver);
         setSecretKey(skey);
@@ -99,8 +102,20 @@ public class CryptoAPIEncryptor extends
      */
     public Cipher initCipherForBlock(Cipher cipher, int block)
     throws GeneralSecurityException {
-        return CryptoAPIDecryptor.initCipherForBlock(cipher, block, builder, getSecretKey(), Cipher.ENCRYPT_MODE);
+        return CryptoAPIDecryptor.initCipherForBlock(cipher, block, getEncryptionInfo(), getSecretKey(), Cipher.ENCRYPT_MODE);
     }    
+
+    @Override
+    public ChunkedCipherOutputStream getDataStream(DirectoryNode dir)
+    throws IOException, GeneralSecurityException {
+        throw new IOException("not supported");
+    }
+    
+    @Override
+    public CryptoAPICipherOutputStream getDataStream(OutputStream stream, int initialOffset)
+    throws IOException, GeneralSecurityException {
+        return new CryptoAPICipherOutputStream(stream);
+    }
     
     /**
      * Encrypt the Document-/SummaryInformation and other optionally streams.
@@ -109,9 +124,9 @@ public class CryptoAPIEncryptor extends
      * 
      * @see <a href="http://msdn.microsoft.com/en-us/library/dd943321(v=office.12).aspx">2.3.5.4 RC4 CryptoAPI Encrypted Summary Stream</a>
      */
-    public OutputStream getDataStream(DirectoryNode dir)
+    public OutputStream getSummaryEntries(DirectoryNode dir)
     throws IOException, GeneralSecurityException {
-        CipherByteArrayOutputStream bos = new CipherByteArrayOutputStream();
+        CryptoAPIDocumentOutputStream bos = new CryptoAPIDocumentOutputStream(this);
         byte buf[] = new byte[8];
         
         bos.write(buf, 0, 8); // skip header
@@ -124,7 +139,9 @@ public class CryptoAPIEncryptor extends
 
         int block = 0;
         for (String entryName : entryNames) {
-            if (!dir.hasEntry(entryName)) continue;
+            if (!dir.hasEntry(entryName)) {
+                continue;
+            }
             StreamDescriptorEntry descEntry = new StreamDescriptorEntry();
             descEntry.block = block;
             descEntry.streamOffset = bos.size();
@@ -193,15 +210,21 @@ public class CryptoAPIEncryptor extends
     }
 
     protected int getKeySizeInBytes() {
-        return builder.getHeader().getKeySize() / 8;
+        return getEncryptionInfo().getHeader().getKeySize() / 8;
     }
 
+    @Override
+    public void setChunkSize(int chunkSize) {
+        _chunkSize = chunkSize;
+    }
+    
     protected void createEncryptionInfoEntry(DirectoryNode dir) throws IOException {
         DataSpaceMapUtils.addDefaultDataSpace(dir);
-        final EncryptionInfo info = builder.getEncryptionInfo();
-        final CryptoAPIEncryptionHeader header = builder.getHeader();
-        final CryptoAPIEncryptionVerifier verifier = builder.getVerifier();
+        final EncryptionInfo info = getEncryptionInfo();
+        final CryptoAPIEncryptionHeader header = (CryptoAPIEncryptionHeader)getEncryptionInfo().getHeader();
+        final CryptoAPIEncryptionVerifier verifier = (CryptoAPIEncryptionVerifier)getEncryptionInfo().getVerifier();
         EncryptionRecord er = new EncryptionRecord() {
+            @Override
             public void write(LittleEndianByteArrayOutputStream bos) {
                 bos.writeShort(info.getVersionMajor());
                 bos.writeShort(info.getVersionMinor());
@@ -212,44 +235,43 @@ public class CryptoAPIEncryptor extends
         DataSpaceMapUtils.createEncryptionEntry(dir, "EncryptionInfo", er);
     }
 
-    private class CipherByteArrayOutputStream extends ByteArrayOutputStream {
-        Cipher cipher;
-        byte oneByte[] = { 0 };
 
-        public CipherByteArrayOutputStream() throws GeneralSecurityException {
-            setBlock(0);
-        }
-        
-        public byte[] getBuf() {
-            return buf;
-        }
-        
-        public void setSize(int count) {
-            this.count = count;
+    @Override
+    public CryptoAPIEncryptor clone() throws CloneNotSupportedException {
+        return (CryptoAPIEncryptor)super.clone();
+    }
+
+    protected class CryptoAPICipherOutputStream extends ChunkedCipherOutputStream {
+
+        @Override
+        protected Cipher initCipherForBlock(Cipher cipher, int block, boolean lastChunk)
+        throws IOException, GeneralSecurityException {
+            flush();
+            EncryptionInfo ei = getEncryptionInfo();
+            SecretKey sk = getSecretKey();
+            return CryptoAPIDecryptor.initCipherForBlock(cipher, block, ei, sk, Cipher.ENCRYPT_MODE);
         }
-        
-        public void setBlock(int block) throws GeneralSecurityException {
-            cipher = initCipherForBlock(cipher, block);
+
+        @Override
+        protected void calculateChecksum(File file, int i) {
         }
-        
-        public void write(int b) {
-            try {
-                oneByte[0] = (byte)b;
-                cipher.update(oneByte, 0, 1, oneByte, 0);
-                super.write(oneByte);
-            } catch (Exception e) {
-                throw new EncryptedDocumentException(e);
-            }
+
+        @Override
+        protected void createEncryptionInfoEntry(DirectoryNode dir, File tmpFile)
+        throws IOException, GeneralSecurityException {
+            throw new RuntimeException("createEncryptionInfoEntry not supported");
         }
 
-        public void write(byte[] b, int off, int len) {
-            try {
-                cipher.update(b, off, len, b, off);
-                super.write(b, off, len);
-            } catch (Exception e) {
-                throw new EncryptedDocumentException(e);
-            }
+        public CryptoAPICipherOutputStream(OutputStream stream)
+        throws IOException, GeneralSecurityException {
+            super(stream, CryptoAPIEncryptor.this._chunkSize);
         }
 
+        @Override
+        public void flush() throws IOException {
+            writeChunk(false);
+            super.flush();
+        }
     }
+
 }

Modified: poi/trunk/src/java/org/apache/poi/poifs/crypt/standard/StandardDecryptor.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/poifs/crypt/standard/StandardDecryptor.java?rev=1762726&r1=1762725&r2=1762726&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/poifs/crypt/standard/StandardDecryptor.java (original)
+++ poi/trunk/src/java/org/apache/poi/poifs/crypt/standard/StandardDecryptor.java Wed Sep 28 23:36:09 2016
@@ -34,7 +34,6 @@ import org.apache.poi.poifs.crypt.Chaini
 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.EncryptionVerifier;
 import org.apache.poi.poifs.crypt.HashAlgorithm;
 import org.apache.poi.poifs.filesystem.DirectoryNode;
@@ -44,15 +43,15 @@ import org.apache.poi.util.LittleEndian;
 
 /**
  */
-public class StandardDecryptor extends Decryptor {
+public class StandardDecryptor extends Decryptor implements Cloneable {
     private long _length = -1;
 
-    protected StandardDecryptor(EncryptionInfoBuilder builder) {
-        super(builder);
+    protected StandardDecryptor() {
     }
 
+    @Override
     public boolean verifyPassword(String password) {
-        EncryptionVerifier ver = builder.getVerifier();
+        EncryptionVerifier ver = getEncryptionInfo().getVerifier();
         SecretKey skey = generateSecretKey(password, ver, getKeySizeInBytes());
         Cipher cipher = getCipher(skey);
 
@@ -116,12 +115,13 @@ public class StandardDecryptor extends D
     }
 
     private Cipher getCipher(SecretKey key) {
-        EncryptionHeader em = builder.getHeader();
+        EncryptionHeader em = getEncryptionInfo().getHeader();
         ChainingMode cm = em.getChainingMode();
         assert(cm == ChainingMode.ecb);
         return CryptoFunctions.getCipher(key, em.getCipherAlgorithm(), cm, null, Cipher.DECRYPT_MODE);
     }
 
+    @Override
     @SuppressWarnings("resource")
     public InputStream getDataStream(DirectoryNode dir) throws IOException {
         DocumentInputStream dis = dir.createDocumentInputStream(DEFAULT_POIFS_ENTRY);
@@ -134,7 +134,7 @@ public class StandardDecryptor extends D
         // limit wrong calculated ole entries - (bug #57080)
         // standard encryption always uses aes encoding, so blockSize is always 16 
         // http://stackoverflow.com/questions/3283787/size-of-data-after-aes-encryption
-        int blockSize = builder.getHeader().getCipherAlgorithm().blockSize;
+        int blockSize = getEncryptionInfo().getHeader().getCipherAlgorithm().blockSize;
         long cipherLen = (_length/blockSize + 1) * blockSize;
         Cipher cipher = getCipher(getSecretKey());
         
@@ -145,8 +145,16 @@ public class StandardDecryptor extends D
     /**
      * @return the length of the stream returned by {@link #getDataStream(DirectoryNode)}
      */
+    @Override
     public long getLength(){
-        if(_length == -1) throw new IllegalStateException("Decryptor.getDataStream() was not called");
+        if(_length == -1) {
+            throw new IllegalStateException("Decryptor.getDataStream() was not called");
+        }
         return _length;
     }
+
+    @Override
+    public StandardDecryptor clone() throws CloneNotSupportedException {
+        return (StandardDecryptor)super.clone();
+    }
 }

Modified: poi/trunk/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptionHeader.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptionHeader.java?rev=1762726&r1=1762725&r2=1762726&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptionHeader.java (original)
+++ poi/trunk/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptionHeader.java Wed Sep 28 23:36:09 2016
@@ -22,6 +22,7 @@ import static org.apache.poi.poifs.crypt
 import java.io.IOException;
 import java.io.InputStream;
 
+import org.apache.poi.hssf.record.RecordInputStream;
 import org.apache.poi.poifs.crypt.ChainingMode;
 import org.apache.poi.poifs.crypt.CipherAlgorithm;
 import org.apache.poi.poifs.crypt.CipherProvider;
@@ -33,7 +34,7 @@ import org.apache.poi.util.LittleEndianI
 import org.apache.poi.util.LittleEndianOutput;
 import org.apache.poi.util.StringUtil;
 
-public class StandardEncryptionHeader extends EncryptionHeader implements EncryptionRecord {
+public class StandardEncryptionHeader extends EncryptionHeader implements EncryptionRecord, Cloneable {
 
     protected StandardEncryptionHeader(LittleEndianInput is) throws IOException {
         setFlags(is.readInt());
@@ -55,9 +56,17 @@ public class StandardEncryptionHeader ex
 
         // CSPName may not always be specified
         // In some cases, the salt value of the EncryptionVerifier is the next chunk of data
-        ((InputStream)is).mark(LittleEndianConsts.INT_SIZE+1);
+        if (is instanceof RecordInputStream) {
+            ((RecordInputStream)is).mark(LittleEndianConsts.INT_SIZE+1);
+        } else {
+            ((InputStream)is).mark(LittleEndianConsts.INT_SIZE+1);
+        }
         int checkForSalt = is.readInt();
-        ((InputStream)is).reset();
+        if (is instanceof RecordInputStream) {
+            ((RecordInputStream)is).reset();
+        } else {
+            ((InputStream)is).reset();
+        }
         
         if (checkForSalt == 16) {
             setCspName("");
@@ -65,7 +74,9 @@ public class StandardEncryptionHeader ex
             StringBuilder builder = new StringBuilder();
             while (true) {
                 char c = (char) is.readShort();
-                if (c == 0) break;
+                if (c == 0) {
+                    break;
+                }
                 builder.append(c);
             }
             setCspName(builder.toString());
@@ -90,6 +101,7 @@ public class StandardEncryptionHeader ex
     /**
      * serializes the header 
      */
+    @Override
     public void write(LittleEndianByteArrayOutputStream bos) {
         int startIdx = bos.getWriteIndex();
         LittleEndianOutput sizeOutput = bos.createDelayedOutput(LittleEndianConsts.INT_SIZE);
@@ -102,10 +114,17 @@ public class StandardEncryptionHeader ex
         bos.writeInt(0); // reserved1
         bos.writeInt(0); // reserved2
         String cspName = getCspName();
-        if (cspName == null) cspName = getCipherProvider().cipherProviderName;
+        if (cspName == null) {
+            cspName = getCipherProvider().cipherProviderName;
+        }
         bos.write(StringUtil.getToUnicodeLE(cspName));
         bos.writeShort(0);
         int headerSize = bos.getWriteIndex()-startIdx-LittleEndianConsts.INT_SIZE;
         sizeOutput.writeInt(headerSize);        
     }
+
+    @Override
+    public StandardEncryptionHeader clone() throws CloneNotSupportedException {
+        return (StandardEncryptionHeader)super.clone();
+    }
 }

Modified: poi/trunk/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptionInfoBuilder.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptionInfoBuilder.java?rev=1762726&r1=1762725&r2=1762726&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptionInfoBuilder.java (original)
+++ poi/trunk/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptionInfoBuilder.java Wed Sep 28 23:36:09 2016
@@ -27,34 +27,29 @@ import org.apache.poi.poifs.crypt.HashAl
 import org.apache.poi.util.LittleEndianInput;
 
 public class StandardEncryptionInfoBuilder implements EncryptionInfoBuilder {
-    
-    EncryptionInfo info;
-    StandardEncryptionHeader header;
-    StandardEncryptionVerifier verifier;
-    StandardDecryptor decryptor;
-    StandardEncryptor encryptor;
 
     /**
      * initialize the builder from a stream
      */
+    @Override
     public void initialize(EncryptionInfo info, LittleEndianInput dis) throws IOException {
-        this.info = info;
-        
         /* int hSize = */ dis.readInt();
-        header = new StandardEncryptionHeader(dis);
-        verifier = new StandardEncryptionVerifier(dis, header);
+        StandardEncryptionHeader header = new StandardEncryptionHeader(dis);
+        info.setHeader(header);
+        info.setVerifier(new StandardEncryptionVerifier(dis, header));
 
         if (info.getVersionMinor() == 2 && (info.getVersionMajor() == 3 || info.getVersionMajor() == 4)) {
-            decryptor = new StandardDecryptor(this);
+            StandardDecryptor dec = new StandardDecryptor();
+            dec.setEncryptionInfo(info);
+            info.setDecryptor(dec);
         }
     }
     
     /**
      * initialize the builder from scratch
      */
+    @Override
     public void initialize(EncryptionInfo info, CipherAlgorithm cipherAlgorithm, HashAlgorithm hashAlgorithm, int keyBits, int blockSize, ChainingMode chainingMode) {
-        this.info = info;
-
         if (cipherAlgorithm == null) {
             cipherAlgorithm = CipherAlgorithm.aes128;
         }
@@ -89,29 +84,13 @@ public class StandardEncryptionInfoBuild
         if (!found) {
             throw new EncryptedDocumentException("KeySize "+keyBits+" not allowed for Cipher "+cipherAlgorithm.toString());
         }
-        header = new StandardEncryptionHeader(cipherAlgorithm, hashAlgorithm, keyBits, blockSize, chainingMode);
-        verifier = new StandardEncryptionVerifier(cipherAlgorithm, hashAlgorithm, keyBits, blockSize, chainingMode);
-        decryptor = new StandardDecryptor(this);
-        encryptor = new StandardEncryptor(this);
-    }
-
-    public StandardEncryptionHeader getHeader() {
-        return header;
-    }
-
-    public StandardEncryptionVerifier getVerifier() {
-        return verifier;
-    }
-
-    public StandardDecryptor getDecryptor() {
-        return decryptor;
-    }
-
-    public StandardEncryptor getEncryptor() {
-        return encryptor;
-    }
-    
-    public EncryptionInfo getEncryptionInfo() {
-        return info;
+        info.setHeader(new StandardEncryptionHeader(cipherAlgorithm, hashAlgorithm, keyBits, blockSize, chainingMode));
+        info.setVerifier(new StandardEncryptionVerifier(cipherAlgorithm, hashAlgorithm, keyBits, blockSize, chainingMode));
+        StandardDecryptor dec = new StandardDecryptor();
+        dec.setEncryptionInfo(info);
+        info.setDecryptor(dec);
+        StandardEncryptor enc = new StandardEncryptor();
+        enc.setEncryptionInfo(info);
+        info.setEncryptor(enc);
     }
 }

Modified: poi/trunk/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptionVerifier.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptionVerifier.java?rev=1762726&r1=1762725&r2=1762726&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptionVerifier.java (original)
+++ poi/trunk/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptionVerifier.java Wed Sep 28 23:36:09 2016
@@ -27,7 +27,7 @@ import org.apache.poi.util.LittleEndianI
 /**
  * Used when checking if a key is valid for a document 
  */
-public class StandardEncryptionVerifier extends EncryptionVerifier implements EncryptionRecord {
+public class StandardEncryptionVerifier extends EncryptionVerifier implements EncryptionRecord, Cloneable {
     private static final int SPIN_COUNT = 50000;
     private final int verifierHashSize;
     
@@ -68,6 +68,7 @@ public class StandardEncryptionVerifier
     }
 
     // make method visible for this package
+    @Override
     protected void setSalt(byte salt[]) {
         if (salt == null || salt.length != 16) {
             throw new EncryptedDocumentException("invalid verifier salt");
@@ -76,15 +77,18 @@ public class StandardEncryptionVerifier
     }
     
     // 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);
     }
     
+    @Override
     public void write(LittleEndianByteArrayOutputStream bos) {
         // see [MS-OFFCRYPTO] - 2.3.4.9
         byte salt[] = getSalt();
@@ -115,4 +119,9 @@ public class StandardEncryptionVerifier
     protected int getVerifierHashSize() {
         return verifierHashSize;
     }
+
+    @Override
+    public StandardEncryptionVerifier clone() throws CloneNotSupportedException {
+        return (StandardEncryptionVerifier)super.clone();
+    }
 }

Modified: poi/trunk/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptor.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptor.java?rev=1762726&r1=1762725&r2=1762726&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptor.java (original)
+++ poi/trunk/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptor.java Wed Sep 28 23:36:09 2016
@@ -53,15 +53,13 @@ import org.apache.poi.util.POILogFactory
 import org.apache.poi.util.POILogger;
 import org.apache.poi.util.TempFile;
 
-public class StandardEncryptor extends Encryptor {
+public class StandardEncryptor extends Encryptor implements Cloneable {
     private static final POILogger logger = POILogFactory.getLogger(StandardEncryptor.class);
 
-    private final StandardEncryptionInfoBuilder builder;
-    
-    protected StandardEncryptor(StandardEncryptionInfoBuilder builder) {
-        this.builder = builder;
+    protected StandardEncryptor() {
     }    
 
+    @Override
     public void confirmPassword(String password) {
         // see [MS-OFFCRYPTO] - 2.3.3 EncryptionVerifier
         Random r = new SecureRandom();
@@ -79,8 +77,9 @@ public class StandardEncryptor extends E
      * 
      * see [MS-OFFCRYPTO] - 2.3.4.7 ECMA-376 Document Encryption Key Generation
      */
+    @Override
     public void confirmPassword(String password, byte keySpec[], byte keySalt[], byte verifier[], byte verifierSalt[], byte integritySalt[]) {
-        StandardEncryptionVerifier ver = builder.getVerifier();
+        StandardEncryptionVerifier ver = (StandardEncryptionVerifier)getEncryptionInfo().getVerifier();
 
         ver.setSalt(verifierSalt);
         SecretKey secretKey = generateSecretKey(password, ver, getKeySizeInBytes());
@@ -111,10 +110,11 @@ public class StandardEncryptor extends E
     }
 
     private Cipher getCipher(SecretKey key, String padding) {
-        EncryptionVerifier ver = builder.getVerifier();
+        EncryptionVerifier ver = getEncryptionInfo().getVerifier();
         return CryptoFunctions.getCipher(key, ver.getCipherAlgorithm(), ver.getChainingMode(), null, Cipher.ENCRYPT_MODE, padding);
     }
     
+    @Override
     public OutputStream getDataStream(final DirectoryNode dir)
     throws IOException, GeneralSecurityException {
         createEncryptionInfoEntry(dir);
@@ -163,6 +163,7 @@ public class StandardEncryptor extends E
             countBytes++;
         }
     
+        @Override
         public void close() throws IOException {
             // the CipherOutputStream adds the padding bytes on close()
             super.close(); 
@@ -175,6 +176,7 @@ public class StandardEncryptor extends E
             // TODO: any properties???
         }
     
+        @Override
         public void processPOIFSWriterEvent(POIFSWriterEvent event) {
             try {
                 LittleEndianOutputStream leos = new LittleEndianOutputStream(event.getStream());
@@ -200,15 +202,16 @@ public class StandardEncryptor extends E
     }
     
     protected int getKeySizeInBytes() {
-        return builder.getHeader().getKeySize()/8;
+        return getEncryptionInfo().getHeader().getKeySize()/8;
     }
     
     protected void createEncryptionInfoEntry(DirectoryNode dir) throws IOException {
-        final EncryptionInfo info = builder.getEncryptionInfo();
-        final StandardEncryptionHeader header = builder.getHeader();
-        final StandardEncryptionVerifier verifier = builder.getVerifier();
+        final EncryptionInfo info = getEncryptionInfo();
+        final StandardEncryptionHeader header = (StandardEncryptionHeader)info.getHeader();
+        final StandardEncryptionVerifier verifier = (StandardEncryptionVerifier)info.getVerifier();
         
         EncryptionRecord er = new EncryptionRecord(){
+            @Override
             public void write(LittleEndianByteArrayOutputStream bos) {
                 bos.writeShort(info.getVersionMajor());
                 bos.writeShort(info.getVersionMinor());
@@ -222,4 +225,9 @@ public class StandardEncryptor extends E
         
         // TODO: any properties???
     }
+
+    @Override
+    public StandardEncryptor clone() throws CloneNotSupportedException {
+        return (StandardEncryptor)super.clone();
+    }
 }

Modified: poi/trunk/src/java/org/apache/poi/poifs/filesystem/DocumentInputStream.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/poifs/filesystem/DocumentInputStream.java?rev=1762726&r1=1762725&r2=1762726&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/poifs/filesystem/DocumentInputStream.java (original)
+++ poi/trunk/src/java/org/apache/poi/poifs/filesystem/DocumentInputStream.java Wed Sep 28 23:36:09 2016
@@ -189,4 +189,9 @@ public class DocumentInputStream extends
         int i = readInt();
         return i & 0xFFFFFFFFL;
     }
+
+    @Override
+    public void readPlain(byte[] buf, int off, int len) {
+        readFully(buf, off, len);
+    }
 }

Modified: poi/trunk/src/java/org/apache/poi/util/LittleEndianByteArrayInputStream.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/util/LittleEndianByteArrayInputStream.java?rev=1762726&r1=1762725&r2=1762726&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/util/LittleEndianByteArrayInputStream.java (original)
+++ poi/trunk/src/java/org/apache/poi/util/LittleEndianByteArrayInputStream.java Wed Sep 28 23:36:09 2016
@@ -17,103 +17,96 @@
 
 package org.apache.poi.util;
 
+import java.io.ByteArrayInputStream;
+
 /**
  * Adapts a plain byte array to {@link LittleEndianInput}
- *
- * @author Josh Micich
  */
-public final class LittleEndianByteArrayInputStream implements LittleEndianInput {
-	private final byte[] _buf;
-	private final int _endIndex;
-	private int _readIndex;
-
+public final class LittleEndianByteArrayInputStream extends ByteArrayInputStream implements LittleEndianInput {
 	public LittleEndianByteArrayInputStream(byte[] buf, int startOffset, int maxReadLen) { // NOSONAR
-		_buf = buf;
-		_readIndex = startOffset;
-		_endIndex = startOffset + maxReadLen;
+	    super(buf, startOffset, maxReadLen);
 	}
+	
 	public LittleEndianByteArrayInputStream(byte[] buf, int startOffset) {
-		this(buf, startOffset, buf.length - startOffset);
+	    super(buf, startOffset, buf.length - startOffset);
 	}
+	
 	public LittleEndianByteArrayInputStream(byte[] buf) {
-		this(buf, 0, buf.length);
+	    super(buf);
 	}
 
-	public int available() {
-		return _endIndex - _readIndex;
-	}
 	private void checkPosition(int i) {
-		if (i > _endIndex - _readIndex) {
+		if (i > count - pos) {
 			throw new RuntimeException("Buffer overrun");
 		}
 	}
 
 	public int getReadIndex() {
-		return _readIndex;
+		return pos;
 	}
-	public byte readByte() {
+
+	@Override
+    public byte readByte() {
 		checkPosition(1);
-		return _buf[_readIndex++];
+		return (byte)read();
 	}
 
-	public int readInt() {
-		checkPosition(4);
-		int i = _readIndex;
-
-		int b0 = _buf[i++] & 0xFF;
-		int b1 = _buf[i++] & 0xFF;
-		int b2 = _buf[i++] & 0xFF;
-		int b3 = _buf[i++] & 0xFF;
-		_readIndex = i;
-		return (b3 << 24) + (b2 << 16) + (b1 << 8) + (b0 << 0);
-	}
-	public long readLong() {
-		checkPosition(8);
-		int i = _readIndex;
-
-		int b0 = _buf[i++] & 0xFF;
-		int b1 = _buf[i++] & 0xFF;
-		int b2 = _buf[i++] & 0xFF;
-		int b3 = _buf[i++] & 0xFF;
-		int b4 = _buf[i++] & 0xFF;
-		int b5 = _buf[i++] & 0xFF;
-		int b6 = _buf[i++] & 0xFF;
-		int b7 = _buf[i++] & 0xFF;
-		_readIndex = i;
-		return (((long)b7 << 56) +
-				((long)b6 << 48) +
-				((long)b5 << 40) +
-				((long)b4 << 32) +
-				((long)b3 << 24) +
-				(b2 << 16) +
-				(b1 <<  8) +
-				(b0 <<  0));
+	@Override
+    public int readInt() {
+	    final int size = LittleEndianConsts.INT_SIZE;
+		checkPosition(size);
+		int le = LittleEndian.getInt(buf, pos);
+		super.skip(size);
+		return le;
 	}
-	public short readShort() {
-		return (short)readUShort();
-	}
-	public int readUByte() {
-		checkPosition(1);
-		return _buf[_readIndex++] & 0xFF;
+
+	@Override
+    public long readLong() {
+	    final int size = LittleEndianConsts.LONG_SIZE;
+		checkPosition(size);
+		long le = LittleEndian.getLong(buf, pos);
+		super.skip(size);
+		return le;
 	}
-	public int readUShort() {
-		checkPosition(2);
-		int i = _readIndex;
-
-		int b0 = _buf[i++] & 0xFF;
-		int b1 = _buf[i++] & 0xFF;
-		_readIndex = i;
-		return (b1 << 8) + (b0 << 0);
+
+	@Override
+    public short readShort() {
+		return (short)readUShort();
 	}
-	public void readFully(byte[] buf, int off, int len) {
+
+	@Override
+    public int readUByte() {
+	    return readByte() & 0xFF;
+	}
+
+	@Override
+    public int readUShort() {
+        final int size = LittleEndianConsts.SHORT_SIZE;
+        checkPosition(size);
+        int le = LittleEndian.getUShort(buf, pos);
+        super.skip(size);
+        return le;
+	}
+
+    @Override
+    public double readDouble() {
+        return Double.longBitsToDouble(readLong());
+    }
+	
+	@Override
+    public void readFully(byte[] buffer, int off, int len) {
 		checkPosition(len);
-		System.arraycopy(_buf, _readIndex, buf, off, len);
-		_readIndex+=len;
+		read(buffer, off, len);
 	}
-	public void readFully(byte[] buf) {
-		readFully(buf, 0, buf.length);
-	}
-	public double readDouble() {
-		return Double.longBitsToDouble(readLong());
+
+	@Override
+    public void readFully(byte[] buffer) {
+        checkPosition(buffer.length);
+        read(buffer, 0, buffer.length);
 	}
+
+    @Override
+    public void readPlain(byte[] buf, int off, int len) {
+        readFully(buf, off, len);
+    }
 }

Modified: poi/trunk/src/java/org/apache/poi/util/LittleEndianByteArrayOutputStream.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/util/LittleEndianByteArrayOutputStream.java?rev=1762726&r1=1762725&r2=1762726&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/util/LittleEndianByteArrayOutputStream.java (original)
+++ poi/trunk/src/java/org/apache/poi/util/LittleEndianByteArrayOutputStream.java Wed Sep 28 23:36:09 2016
@@ -17,28 +17,26 @@
 
 package org.apache.poi.util;
 
+import java.io.OutputStream;
 
 /**
- * Adapts a plain byte array to {@link LittleEndianOutput} 
- * 
- * 
- * @author Josh Micich
+ * Adapts a plain byte array to {@link LittleEndianOutput}
  */
-public final class LittleEndianByteArrayOutputStream implements LittleEndianOutput, DelayableLittleEndianOutput {
+public final class LittleEndianByteArrayOutputStream extends OutputStream implements LittleEndianOutput, DelayableLittleEndianOutput {
 	private final byte[] _buf;
 	private final int _endIndex;
 	private int _writeIndex;
 
 	public LittleEndianByteArrayOutputStream(byte[] buf, int startOffset, int maxWriteLen) { // NOSONAR
 		if (startOffset < 0 || startOffset > buf.length) {
-			throw new IllegalArgumentException("Specified startOffset (" + startOffset 
+			throw new IllegalArgumentException("Specified startOffset (" + startOffset
 					+ ") is out of allowable range (0.." + buf.length + ")");
 		}
 		_buf = buf;
 		_writeIndex = startOffset;
 		_endIndex = startOffset + maxWriteLen;
 		if (_endIndex < startOffset ||  _endIndex > buf.length) {
-			throw new IllegalArgumentException("calculated end index (" + _endIndex 
+			throw new IllegalArgumentException("calculated end index (" + _endIndex
 					+ ") is out of allowable range (" + _writeIndex + ".." + buf.length + ")");
 		}
 	}
@@ -52,16 +50,19 @@ public final class LittleEndianByteArray
 		}
 	}
 
-	public void writeByte(int v) {
+	@Override
+    public void writeByte(int v) {
 		checkPosition(1);
 		_buf[_writeIndex++] = (byte)v;
 	}
 
-	public void writeDouble(double v) {
+	@Override
+    public void writeDouble(double v) {
 		writeLong(Double.doubleToLongBits(v));
 	}
 
-	public void writeInt(int v) {
+	@Override
+    public void writeInt(int v) {
 		checkPosition(4);
 		int i = _writeIndex;
 		_buf[i++] = (byte)((v >>>  0) & 0xFF);
@@ -71,33 +72,47 @@ public final class LittleEndianByteArray
 		_writeIndex = i;
 	}
 
-	public void writeLong(long v) {
+	@Override
+    public void writeLong(long v) {
 		writeInt((int)(v >>  0));
 		writeInt((int)(v >> 32));
 	}
 
-	public void writeShort(int v) {
+	@Override
+    public void writeShort(int v) {
 		checkPosition(2);
 		int i = _writeIndex;
 		_buf[i++] = (byte)((v >>>  0) & 0xFF);
 		_buf[i++] = (byte)((v >>>  8) & 0xFF);
 		_writeIndex = i;
 	}
-	public void write(byte[] b) {
+
+	@Override
+    public void write(int b) {
+	    writeByte(b);
+    }
+
+	@Override
+    public void write(byte[] b) {
 		int len = b.length;
 		checkPosition(len);
 		System.arraycopy(b, 0, _buf, _writeIndex, len);
 		_writeIndex += len;
 	}
-	public void write(byte[] b, int offset, int len) {
+
+	@Override
+    public void write(byte[] b, int offset, int len) {
 		checkPosition(len);
 		System.arraycopy(b, offset, _buf, _writeIndex, len);
 		_writeIndex += len;
 	}
+
 	public int getWriteIndex() {
 		return _writeIndex;
 	}
-	public LittleEndianOutput createDelayedOutput(int size) {
+
+	@Override
+    public LittleEndianOutput createDelayedOutput(int size) {
 		checkPosition(size);
 		LittleEndianOutput result = new LittleEndianByteArrayOutputStream(_buf, _writeIndex, size);
 		_writeIndex += size;



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


Mime
View raw message