Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 30B56200B9D for ; Thu, 29 Sep 2016 01:36:30 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id 2F373160AD4; Wed, 28 Sep 2016 23:36:30 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id A3317160AD3 for ; Thu, 29 Sep 2016 01:36:27 +0200 (CEST) Received: (qmail 84251 invoked by uid 500); 28 Sep 2016 23:36:26 -0000 Mailing-List: contact commits-help@poi.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@poi.apache.org Delivered-To: mailing list commits@poi.apache.org Received: (qmail 84242 invoked by uid 99); 28 Sep 2016 23:36:26 -0000 Received: from pnap-us-west-generic-nat.apache.org (HELO spamd4-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 28 Sep 2016 23:36:26 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd4-us-west.apache.org (ASF Mail Server at spamd4-us-west.apache.org) with ESMTP id 39500C254F for ; Wed, 28 Sep 2016 23:36:26 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd4-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: -1.199 X-Spam-Level: X-Spam-Status: No, score=-1.199 tagged_above=-999 required=6.31 tests=[KAM_ASCII_DIVIDERS=0.8, KAM_LAZY_DOMAIN_SECURITY=1, RP_MATCHES_RCVD=-2.999] autolearn=disabled Received: from mx2-lw-eu.apache.org ([10.40.0.8]) by localhost (spamd4-us-west.apache.org [10.40.0.11]) (amavisd-new, port 10024) with ESMTP id bKPcZqWsLhRf for ; Wed, 28 Sep 2016 23:36:14 +0000 (UTC) Received: from mailrelay1-us-west.apache.org (mailrelay1-us-west.apache.org [209.188.14.139]) by mx2-lw-eu.apache.org (ASF Mail Server at mx2-lw-eu.apache.org) with ESMTP id E67AA5FADE for ; Wed, 28 Sep 2016 23:36:12 +0000 (UTC) Received: from svn01-us-west.apache.org (svn.apache.org [10.41.0.6]) by mailrelay1-us-west.apache.org (ASF Mail Server at mailrelay1-us-west.apache.org) with ESMTP id C6513E0652 for ; Wed, 28 Sep 2016 23:36:11 +0000 (UTC) Received: from svn01-us-west.apache.org (localhost [127.0.0.1]) by svn01-us-west.apache.org (ASF Mail Server at svn01-us-west.apache.org) with ESMTP id CC3BB3A10BB for ; Wed, 28 Sep 2016 23:36:10 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit 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 -0000 To: commits@poi.apache.org From: kiwiwings@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20160928233610.CC3BB3A10BB@svn01-us-west.apache.org> archived-at: Wed, 28 Sep 2016 23:36:30 -0000 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 2.3.4.5 \EncryptionInfo Stream (Standard Encryption) */ standard("org.apache.poi.poifs.crypt.standard.StandardEncryptionInfoBuilder", 4, 2, 0x24), /* @see 2.3.4.10 \EncryptionInfo Stream (Agile Encryption) */ - agile("org.apache.poi.poifs.crypt.agile.AgileEncryptionInfoBuilder", 4, 4, 0x40) + agile("org.apache.poi.poifs.crypt.agile.AgileEncryptionInfoBuilder", 4, 4, 0x40), + /* @see XOR Obfuscation */ + 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 2.3.5.4 RC4 CryptoAPI Encrypted Summary Stream */ - 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 2.3.5.4 RC4 CryptoAPI Encrypted Summary Stream */ - 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