You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by ki...@apache.org on 2016/08/03 23:54:02 UTC
svn commit: r1755127 [2/3] - in /poi/branches/hssf_cryptoapi/src:
java/org/apache/poi/ java/org/apache/poi/hssf/record/
java/org/apache/poi/poifs/crypt/ java/org/apache/poi/poifs/crypt/binaryrc4/
java/org/apache/poi/poifs/crypt/cryptoapi/ java/org/apac...
Modified: poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptor.java
URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptor.java?rev=1755127&r1=1755126&r2=1755127&view=diff
==============================================================================
--- poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptor.java (original)
+++ poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptor.java Wed Aug 3 23:54:01 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,19 @@ 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");
+ }
+
+ public CryptoAPICipherOutputStream getDataStream(OutputStream stream)
+ throws IOException, GeneralSecurityException {
+ return new CryptoAPICipherOutputStream(stream);
+ }
/**
* Encrypt the Document-/SummaryInformation and other optionally streams.
@@ -109,9 +123,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 +138,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 +209,20 @@ public class CryptoAPIEncryptor extends
}
protected int getKeySizeInBytes() {
- return builder.getHeader().getKeySize() / 8;
+ return getEncryptionInfo().getHeader().getKeySize() / 8;
}
+ 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 +233,42 @@ 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);
+ }
}
+
}
Modified: poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/standard/StandardDecryptor.java
URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/standard/StandardDecryptor.java?rev=1755127&r1=1755126&r2=1755127&view=diff
==============================================================================
--- poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/standard/StandardDecryptor.java (original)
+++ poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/standard/StandardDecryptor.java Wed Aug 3 23:54:01 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/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptionHeader.java
URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptionHeader.java?rev=1755127&r1=1755126&r2=1755127&view=diff
==============================================================================
--- poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptionHeader.java (original)
+++ poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptionHeader.java Wed Aug 3 23:54:01 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/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptionInfoBuilder.java
URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptionInfoBuilder.java?rev=1755127&r1=1755126&r2=1755127&view=diff
==============================================================================
--- poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptionInfoBuilder.java (original)
+++ poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptionInfoBuilder.java Wed Aug 3 23:54:01 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/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptionVerifier.java
URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptionVerifier.java?rev=1755127&r1=1755126&r2=1755127&view=diff
==============================================================================
--- poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptionVerifier.java (original)
+++ poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptionVerifier.java Wed Aug 3 23:54:01 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/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptor.java
URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptor.java?rev=1755127&r1=1755126&r2=1755127&view=diff
==============================================================================
--- poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptor.java (original)
+++ poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptor.java Wed Aug 3 23:54:01 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/branches/hssf_cryptoapi/src/java/org/apache/poi/util/LittleEndianByteArrayInputStream.java
URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/java/org/apache/poi/util/LittleEndianByteArrayInputStream.java?rev=1755127&r1=1755126&r2=1755127&view=diff
==============================================================================
--- poi/branches/hssf_cryptoapi/src/java/org/apache/poi/util/LittleEndianByteArrayInputStream.java (original)
+++ poi/branches/hssf_cryptoapi/src/java/org/apache/poi/util/LittleEndianByteArrayInputStream.java Wed Aug 3 23:54:01 2016
@@ -17,103 +17,91 @@
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;
- }
- public void readFully(byte[] buf) {
- readFully(buf, 0, buf.length);
+ read(buffer, off, len);
}
- public double readDouble() {
- return Double.longBitsToDouble(readLong());
+
+ @Override
+ public void readFully(byte[] buffer) {
+ checkPosition(buffer.length);
+ read(buffer, 0, buffer.length);
}
}
Modified: poi/branches/hssf_cryptoapi/src/java/org/apache/poi/util/LittleEndianByteArrayOutputStream.java
URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/java/org/apache/poi/util/LittleEndianByteArrayOutputStream.java?rev=1755127&r1=1755126&r2=1755127&view=diff
==============================================================================
--- poi/branches/hssf_cryptoapi/src/java/org/apache/poi/util/LittleEndianByteArrayOutputStream.java (original)
+++ poi/branches/hssf_cryptoapi/src/java/org/apache/poi/util/LittleEndianByteArrayOutputStream.java Wed Aug 3 23:54:01 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;
Modified: poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileDecryptor.java
URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileDecryptor.java?rev=1755127&r1=1755126&r2=1755127&view=diff
==============================================================================
--- poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileDecryptor.java (original)
+++ poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileDecryptor.java Wed Aug 3 23:54:01 2016
@@ -45,7 +45,7 @@ import org.apache.poi.poifs.crypt.Cipher
import org.apache.poi.poifs.crypt.CryptoFunctions;
import org.apache.poi.poifs.crypt.Decryptor;
import org.apache.poi.poifs.crypt.EncryptionHeader;
-import org.apache.poi.poifs.crypt.EncryptionInfoBuilder;
+import org.apache.poi.poifs.crypt.EncryptionInfo;
import org.apache.poi.poifs.crypt.EncryptionVerifier;
import org.apache.poi.poifs.crypt.HashAlgorithm;
import org.apache.poi.poifs.crypt.agile.AgileEncryptionVerifier.AgileCertificateEntry;
@@ -56,14 +56,14 @@ import org.apache.poi.util.LittleEndian;
/**
* Decryptor implementation for Agile Encryption
*/
-public class AgileDecryptor extends Decryptor {
+public class AgileDecryptor extends Decryptor implements Cloneable {
private long _length = -1;
- protected static final byte[] kVerifierInputBlock;
- protected static final byte[] kHashedVerifierBlock;
- protected static final byte[] kCryptoKeyBlock;
- protected static final byte[] kIntegrityKeyBlock;
- protected static final byte[] kIntegrityValueBlock;
+ /* package */ static final byte[] kVerifierInputBlock;
+ /* package */ static final byte[] kHashedVerifierBlock;
+ /* package */ static final byte[] kCryptoKeyBlock;
+ /* package */ static final byte[] kIntegrityKeyBlock;
+ /* package */ static final byte[] kIntegrityValueBlock;
static {
kVerifierInputBlock =
@@ -83,16 +83,16 @@ public class AgileDecryptor extends Decr
(byte)0xb2, (byte)0x2c, (byte)0x84, (byte)0x33 };
}
- protected AgileDecryptor(AgileEncryptionInfoBuilder builder) {
- super(builder);
+ protected AgileDecryptor() {
}
/**
* set decryption password
*/
+ @Override
public boolean verifyPassword(String password) throws GeneralSecurityException {
- AgileEncryptionVerifier ver = (AgileEncryptionVerifier)builder.getVerifier();
- AgileEncryptionHeader header = (AgileEncryptionHeader)builder.getHeader();
+ AgileEncryptionVerifier ver = (AgileEncryptionVerifier)getEncryptionInfo().getVerifier();
+ AgileEncryptionHeader header = (AgileEncryptionHeader)getEncryptionInfo().getHeader();
HashAlgorithm hashAlgo = header.getHashAlgorithmEx();
CipherAlgorithm cipherAlgo = header.getCipherAlgorithm();
int blockSize = header.getBlockSize();
@@ -113,7 +113,7 @@ public class AgileDecryptor extends Decr
* blockSize bytes.
* 4. Use base64 to encode the result of step 3.
*/
- byte verfierInputEnc[] = hashInput(builder, pwHash, kVerifierInputBlock, ver.getEncryptedVerifier(), Cipher.DECRYPT_MODE);
+ byte verfierInputEnc[] = hashInput(getEncryptionInfo(), pwHash, kVerifierInputBlock, ver.getEncryptedVerifier(), Cipher.DECRYPT_MODE);
setVerifier(verfierInputEnc);
MessageDigest hashMD = getMessageDigest(hashAlgo);
byte[] verifierHash = hashMD.digest(verfierInputEnc);
@@ -130,7 +130,7 @@ public class AgileDecryptor extends Decr
* blockSize bytes, pad the hash value with 0x00 to an integral multiple of blockSize bytes.
* 4. Use base64 to encode the result of step 3.
*/
- byte verifierHashDec[] = hashInput(builder, pwHash, kHashedVerifierBlock, ver.getEncryptedVerifierHash(), Cipher.DECRYPT_MODE);
+ byte verifierHashDec[] = hashInput(getEncryptionInfo(), pwHash, kHashedVerifierBlock, ver.getEncryptedVerifierHash(), Cipher.DECRYPT_MODE);
verifierHashDec = getBlock0(verifierHashDec, hashAlgo.hashSize);
/**
@@ -146,7 +146,7 @@ public class AgileDecryptor extends Decr
* blockSize bytes.
* 4. Use base64 to encode the result of step 3.
*/
- byte keyspec[] = hashInput(builder, pwHash, kCryptoKeyBlock, ver.getEncryptedKey(), Cipher.DECRYPT_MODE);
+ byte keyspec[] = hashInput(getEncryptionInfo(), pwHash, kCryptoKeyBlock, ver.getEncryptedKey(), Cipher.DECRYPT_MODE);
keyspec = getBlock0(keyspec, keySize);
SecretKeySpec secretKey = new SecretKeySpec(keyspec, ver.getCipherAlgorithm().jceId);
@@ -204,8 +204,8 @@ public class AgileDecryptor extends Decr
* @throws GeneralSecurityException
*/
public boolean verifyPassword(KeyPair keyPair, X509Certificate x509) throws GeneralSecurityException {
- AgileEncryptionVerifier ver = (AgileEncryptionVerifier)builder.getVerifier();
- AgileEncryptionHeader header = (AgileEncryptionHeader)builder.getHeader();
+ AgileEncryptionVerifier ver = (AgileEncryptionVerifier)getEncryptionInfo().getVerifier();
+ AgileEncryptionHeader header = (AgileEncryptionHeader)getEncryptionInfo().getHeader();
HashAlgorithm hashAlgo = header.getHashAlgorithmEx();
CipherAlgorithm cipherAlgo = header.getCipherAlgorithm();
int blockSize = header.getBlockSize();
@@ -217,7 +217,9 @@ public class AgileDecryptor extends Decr
break;
}
}
- if (ace == null) return false;
+ if (ace == null) {
+ return false;
+ }
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, keyPair.getPrivate());
@@ -255,9 +257,9 @@ public class AgileDecryptor extends Decr
return fillSize;
}
- protected static byte[] hashInput(EncryptionInfoBuilder builder, byte pwHash[], byte blockKey[], byte inputKey[], int cipherMode) {
- EncryptionVerifier ver = builder.getVerifier();
- AgileDecryptor dec = (AgileDecryptor)builder.getDecryptor();
+ protected static byte[] hashInput(EncryptionInfo encryptionInfo, byte pwHash[], byte blockKey[], byte inputKey[], int cipherMode) {
+ EncryptionVerifier ver = encryptionInfo.getVerifier();
+ AgileDecryptor dec = (AgileDecryptor)encryptionInfo.getDecryptor();
int keySize = dec.getKeySizeInBytes();
int blockSize = dec.getBlockSizeInBytes();
HashAlgorithm hashAlgo = ver.getHashAlgorithm();
@@ -278,6 +280,7 @@ public class AgileDecryptor extends Decr
}
}
+ @Override
@SuppressWarnings("resource")
public InputStream getDataStream(DirectoryNode dir) throws IOException, GeneralSecurityException {
DocumentInputStream dis = dir.createDocumentInputStream(DEFAULT_POIFS_ENTRY);
@@ -285,17 +288,20 @@ public class AgileDecryptor extends Decr
return new AgileCipherInputStream(dis, _length);
}
+ @Override
public long getLength(){
- if(_length == -1) throw new IllegalStateException("EcmaDecryptor.getDataStream() was not called");
+ if(_length == -1) {
+ throw new IllegalStateException("EcmaDecryptor.getDataStream() was not called");
+ }
return _length;
}
- protected static Cipher initCipherForBlock(Cipher existing, int block, boolean lastChunk, EncryptionInfoBuilder builder, SecretKey skey, int encryptionMode)
+ protected static Cipher initCipherForBlock(Cipher existing, int block, boolean lastChunk, EncryptionInfo encryptionInfo, SecretKey skey, int encryptionMode)
throws GeneralSecurityException {
- EncryptionHeader header = builder.getHeader();
- if (existing == null || lastChunk) {
- String padding = (lastChunk ? "PKCS5Padding" : "NoPadding");
+ EncryptionHeader header = encryptionInfo.getHeader();
+ String padding = (lastChunk ? "PKCS5Padding" : "NoPadding");
+ if (existing == null || !existing.getAlgorithm().endsWith(padding)) {
existing = getCipher(skey, header.getCipherAlgorithm(), header.getChainingMode(), header.getKeySalt(), encryptionMode, padding);
}
@@ -339,9 +345,15 @@ public class AgileDecryptor extends Decr
// TODO: calculate integrity hmac while reading the stream
// for a post-validation of the data
+ @Override
protected Cipher initCipherForBlock(Cipher cipher, int block)
throws GeneralSecurityException {
- return AgileDecryptor.initCipherForBlock(cipher, block, false, builder, getSecretKey(), Cipher.DECRYPT_MODE);
+ return AgileDecryptor.initCipherForBlock(cipher, block, false, getEncryptionInfo(), getSecretKey(), Cipher.DECRYPT_MODE);
}
}
+
+ @Override
+ public AgileDecryptor clone() throws CloneNotSupportedException {
+ return (AgileDecryptor)super.clone();
+ }
}
Modified: poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptionHeader.java
URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptionHeader.java?rev=1755127&r1=1755126&r2=1755127&view=diff
==============================================================================
--- poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptionHeader.java (original)
+++ poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptionHeader.java Wed Aug 3 23:54:01 2016
@@ -27,7 +27,7 @@ import com.microsoft.schemas.office.x200
import com.microsoft.schemas.office.x2006.encryption.EncryptionDocument;
import com.microsoft.schemas.office.x2006.encryption.STCipherChaining;
-public class AgileEncryptionHeader extends EncryptionHeader {
+public class AgileEncryptionHeader extends EncryptionHeader implements Cloneable {
private byte encryptedHmacKey[], encryptedHmacValue[];
public AgileEncryptionHeader(String descriptor) {
@@ -99,6 +99,7 @@ public class AgileEncryptionHeader exten
}
// make method visible for this package
+ @Override
protected void setKeySalt(byte salt[]) {
if (salt == null || salt.length != getBlockSize()) {
throw new EncryptedDocumentException("invalid verifier salt");
@@ -121,4 +122,13 @@ public class AgileEncryptionHeader exten
protected void setEncryptedHmacValue(byte[] encryptedHmacValue) {
this.encryptedHmacValue = (encryptedHmacValue == null) ? null : encryptedHmacValue.clone();
}
+
+ @Override
+ public AgileEncryptionHeader clone() throws CloneNotSupportedException {
+ AgileEncryptionHeader other = (AgileEncryptionHeader)super.clone();
+ other.encryptedHmacKey = (encryptedHmacKey == null) ? null : encryptedHmacKey.clone();
+ other.encryptedHmacValue = (encryptedHmacValue == null) ? null : encryptedHmacValue.clone();
+ return other;
+ }
+
}
Modified: poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptionInfoBuilder.java
URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptionInfoBuilder.java?rev=1755127&r1=1755126&r2=1755127&view=diff
==============================================================================
--- poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptionInfoBuilder.java (original)
+++ poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptionInfoBuilder.java Wed Aug 3 23:54:01 2016
@@ -35,30 +35,24 @@ import com.microsoft.schemas.office.x200
public class AgileEncryptionInfoBuilder implements EncryptionInfoBuilder {
- EncryptionInfo info;
- AgileEncryptionHeader header;
- AgileEncryptionVerifier verifier;
- AgileDecryptor decryptor;
- AgileEncryptor encryptor;
-
@Override
- public void initialize(EncryptionInfo ei, LittleEndianInput dis) throws IOException {
- this.info = ei;
-
+ public void initialize(EncryptionInfo info, LittleEndianInput dis) throws IOException {
EncryptionDocument ed = parseDescriptor((InputStream)dis);
- header = new AgileEncryptionHeader(ed);
- verifier = new AgileEncryptionVerifier(ed);
- if (ei.getVersionMajor() == EncryptionMode.agile.versionMajor
- && ei.getVersionMinor() == EncryptionMode.agile.versionMinor) {
- decryptor = new AgileDecryptor(this);
- encryptor = new AgileEncryptor(this);
+ info.setHeader(new AgileEncryptionHeader(ed));
+ info.setVerifier(new AgileEncryptionVerifier(ed));
+ if (info.getVersionMajor() == EncryptionMode.agile.versionMajor
+ && info.getVersionMinor() == EncryptionMode.agile.versionMinor) {
+ AgileDecryptor dec = new AgileDecryptor();
+ dec.setEncryptionInfo(info);
+ info.setDecryptor(dec);
+ AgileEncryptor enc = new AgileEncryptor();
+ enc.setEncryptionInfo(info);
+ info.setEncryptor(enc);
}
}
@Override
- public void initialize(EncryptionInfo ei, CipherAlgorithm cipherAlgorithm, HashAlgorithm hashAlgorithm, int keyBits, int blockSize, ChainingMode chainingMode) {
- this.info = ei;
-
+ public void initialize(EncryptionInfo info, CipherAlgorithm cipherAlgorithm, HashAlgorithm hashAlgorithm, int keyBits, int blockSize, ChainingMode chainingMode) {
if (cipherAlgorithm == null) {
cipherAlgorithm = CipherAlgorithm.aes128;
}
@@ -87,30 +81,14 @@ public class AgileEncryptionInfoBuilder
if (!found) {
throw new EncryptedDocumentException("KeySize "+keyBits+" not allowed for Cipher "+cipherAlgorithm.toString());
}
- header = new AgileEncryptionHeader(cipherAlgorithm, hashAlgorithm, keyBits, blockSize, chainingMode);
- verifier = new AgileEncryptionVerifier(cipherAlgorithm, hashAlgorithm, keyBits, blockSize, chainingMode);
- decryptor = new AgileDecryptor(this);
- encryptor = new AgileEncryptor(this);
- }
-
- public AgileEncryptionHeader getHeader() {
- return header;
- }
-
- public AgileEncryptionVerifier getVerifier() {
- return verifier;
- }
-
- public AgileDecryptor getDecryptor() {
- return decryptor;
- }
-
- public AgileEncryptor getEncryptor() {
- return encryptor;
- }
-
- protected EncryptionInfo getInfo() {
- return info;
+ info.setHeader(new AgileEncryptionHeader(cipherAlgorithm, hashAlgorithm, keyBits, blockSize, chainingMode));
+ info.setVerifier(new AgileEncryptionVerifier(cipherAlgorithm, hashAlgorithm, keyBits, blockSize, chainingMode));
+ AgileDecryptor dec = new AgileDecryptor();
+ dec.setEncryptionInfo(info);
+ info.setDecryptor(dec);
+ AgileEncryptor enc = new AgileEncryptor();
+ enc.setEncryptionInfo(info);
+ info.setEncryptor(enc);
}
protected static EncryptionDocument parseDescriptor(String descriptor) {
Modified: poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptionVerifier.java
URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptionVerifier.java?rev=1755127&r1=1755126&r2=1755127&view=diff
==============================================================================
--- poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptionVerifier.java (original)
+++ poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptionVerifier.java Wed Aug 3 23:54:01 2016
@@ -39,7 +39,7 @@ import com.microsoft.schemas.office.x200
/**
* Used when checking if a key is valid for a document
*/
-public class AgileEncryptionVerifier extends EncryptionVerifier {
+public class AgileEncryptionVerifier extends EncryptionVerifier implements Cloneable {
public static class AgileCertificateEntry {
X509Certificate x509;
@@ -87,8 +87,9 @@ public class AgileEncryptionVerifier ext
setEncryptedVerifierHash(keyData.getEncryptedVerifierHashValue());
int saltSize = keyData.getSaltSize();
- if (saltSize != getSalt().length)
+ if (saltSize != getSalt().length) {
throw new EncryptedDocumentException("Invalid salt size");
+ }
switch (keyData.getCipherChaining().intValue()) {
case STCipherChaining.INT_CHAINING_MODE_CBC:
@@ -101,7 +102,9 @@ public class AgileEncryptionVerifier ext
throw new EncryptedDocumentException("Unsupported chaining mode - "+keyData.getCipherChaining().toString());
}
- if (!encList.hasNext()) return;
+ if (!encList.hasNext()) {
+ return;
+ }
try {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
@@ -125,6 +128,7 @@ public class AgileEncryptionVerifier ext
setSpinCount(100000); // TODO: use parameter
}
+ @Override
protected void setSalt(byte salt[]) {
if (salt == null || salt.length != getCipherAlgorithm().blockSize) {
throw new EncryptedDocumentException("invalid verifier salt");
@@ -133,16 +137,19 @@ public class AgileEncryptionVerifier ext
}
// make method visible for this package
+ @Override
protected void setEncryptedVerifier(byte encryptedVerifier[]) {
super.setEncryptedVerifier(encryptedVerifier);
}
// make method visible for this package
+ @Override
protected void setEncryptedVerifierHash(byte encryptedVerifierHash[]) {
super.setEncryptedVerifierHash(encryptedVerifierHash);
}
// make method visible for this package
+ @Override
protected void setEncryptedKey(byte[] encryptedKey) {
super.setEncryptedKey(encryptedKey);
}
@@ -156,4 +163,12 @@ public class AgileEncryptionVerifier ext
public List<AgileCertificateEntry> getCertificates() {
return certList;
}
+
+ @Override
+ public AgileEncryptionVerifier clone() throws CloneNotSupportedException {
+ AgileEncryptionVerifier other = (AgileEncryptionVerifier)super.clone();
+ // TODO: deep copy of certList
+ other.certList = new ArrayList<AgileCertificateEntry>(certList);
+ return other;
+ }
}
Modified: poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptor.java
URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptor.java?rev=1755127&r1=1755126&r2=1755127&view=diff
==============================================================================
--- poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptor.java (original)
+++ poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptor.java Wed Aug 3 23:54:01 2016
@@ -60,6 +60,7 @@ import org.apache.poi.poifs.crypt.standa
import org.apache.poi.poifs.filesystem.DirectoryNode;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianByteArrayOutputStream;
+import org.apache.poi.util.LittleEndianConsts;
import org.apache.xmlbeans.XmlOptions;
import com.microsoft.schemas.office.x2006.encryption.CTDataIntegrity;
@@ -74,21 +75,20 @@ import com.microsoft.schemas.office.x200
import com.microsoft.schemas.office.x2006.keyEncryptor.certificate.CTCertificateKeyEncryptor;
import com.microsoft.schemas.office.x2006.keyEncryptor.password.CTPasswordKeyEncryptor;
-public class AgileEncryptor extends Encryptor {
- private final AgileEncryptionInfoBuilder builder;
+public class AgileEncryptor extends Encryptor implements Cloneable {
private byte integritySalt[];
private byte pwHash[];
- protected AgileEncryptor(AgileEncryptionInfoBuilder builder) {
- this.builder = builder;
+ protected AgileEncryptor() {
}
+ @Override
public void confirmPassword(String password) {
// see [MS-OFFCRYPTO] - 2.3.3 EncryptionVerifier
Random r = new SecureRandom();
- int blockSize = builder.getHeader().getBlockSize();
- int keySize = builder.getHeader().getKeySize()/8;
- int hashSize = builder.getHeader().getHashAlgorithmEx().hashSize;
+ int blockSize = getEncryptionInfo().getHeader().getBlockSize();
+ int keySize = getEncryptionInfo().getHeader().getKeySize()/8;
+ int hashSize = getEncryptionInfo().getHeader().getHashAlgorithmEx().hashSize;
byte[] newVerifierSalt = new byte[blockSize]
, newVerifier = new byte[blockSize]
@@ -104,10 +104,11 @@ public class AgileEncryptor extends Encr
confirmPassword(password, newKeySpec, newKeySalt, newVerifierSalt, newVerifier, newIntegritySalt);
}
- public void confirmPassword(String password, byte keySpec[], byte keySalt[], byte verifier[], byte verifierSalt[], byte integritySalt[]) {
- AgileEncryptionVerifier ver = builder.getVerifier();
+ @Override
+ public void confirmPassword(String password, byte keySpec[], byte keySalt[], byte verifier[], byte verifierSalt[], byte integritySalt[]) {
+ AgileEncryptionVerifier ver = (AgileEncryptionVerifier)getEncryptionInfo().getVerifier();
ver.setSalt(verifierSalt);
- AgileEncryptionHeader header = builder.getHeader();
+ AgileEncryptionHeader header = (AgileEncryptionHeader)getEncryptionInfo().getHeader();
header.setKeySalt(keySalt);
HashAlgorithm hashAlgo = ver.getHashAlgorithm();
@@ -128,7 +129,7 @@ public class AgileEncryptor extends Encr
* blockSize bytes.
* 4. Use base64 to encode the result of step 3.
*/
- byte encryptedVerifier[] = hashInput(builder, pwHash, kVerifierInputBlock, verifier, Cipher.ENCRYPT_MODE);
+ byte encryptedVerifier[] = hashInput(getEncryptionInfo(), pwHash, kVerifierInputBlock, verifier, Cipher.ENCRYPT_MODE);
ver.setEncryptedVerifier(encryptedVerifier);
@@ -146,7 +147,7 @@ public class AgileEncryptor extends Encr
*/
MessageDigest hashMD = getMessageDigest(hashAlgo);
byte[] hashedVerifier = hashMD.digest(verifier);
- byte encryptedVerifierHash[] = hashInput(builder, pwHash, kHashedVerifierBlock, hashedVerifier, Cipher.ENCRYPT_MODE);
+ byte encryptedVerifierHash[] = hashInput(getEncryptionInfo(), pwHash, kHashedVerifierBlock, hashedVerifier, Cipher.ENCRYPT_MODE);
ver.setEncryptedVerifierHash(encryptedVerifierHash);
/**
@@ -162,7 +163,7 @@ public class AgileEncryptor extends Encr
* blockSize bytes.
* 4. Use base64 to encode the result of step 3.
*/
- byte encryptedKey[] = hashInput(builder, pwHash, kCryptoKeyBlock, keySpec, Cipher.ENCRYPT_MODE);
+ byte encryptedKey[] = hashInput(getEncryptionInfo(), pwHash, kCryptoKeyBlock, keySpec, Cipher.ENCRYPT_MODE);
ver.setEncryptedKey(encryptedKey);
SecretKey secretKey = new SecretKeySpec(keySpec, ver.getCipherAlgorithm().jceId);
@@ -214,6 +215,7 @@ public class AgileEncryptor extends Encr
}
}
+ @Override
public OutputStream getDataStream(DirectoryNode dir)
throws IOException, GeneralSecurityException {
// TODO: initialize headers
@@ -234,14 +236,14 @@ public class AgileEncryptor extends Encr
// as the integrity hmac needs to contain the StreamSize,
// it's not possible to calculate it on-the-fly while buffering
// TODO: add stream size parameter to getDataStream()
- AgileEncryptionVerifier ver = builder.getVerifier();
+ AgileEncryptionVerifier ver = (AgileEncryptionVerifier)getEncryptionInfo().getVerifier();
HashAlgorithm hashAlgo = ver.getHashAlgorithm();
Mac integrityMD = CryptoFunctions.getMac(hashAlgo);
integrityMD.init(new SecretKeySpec(integritySalt, hashAlgo.jceHmacId));
byte buf[] = new byte[1024];
LittleEndian.putLong(buf, 0, oleStreamSize);
- integrityMD.update(buf, 0, LittleEndian.LONG_SIZE);
+ integrityMD.update(buf, 0, LittleEndianConsts.LONG_SIZE);
InputStream fis = new FileInputStream(tmpFile);
try {
@@ -255,7 +257,7 @@ public class AgileEncryptor extends Encr
byte hmacValue[] = integrityMD.doFinal();
- AgileEncryptionHeader header = builder.getHeader();
+ AgileEncryptionHeader header = (AgileEncryptionHeader)getEncryptionInfo().getHeader();
int blockSize = header.getBlockSize();
byte iv[] = CryptoFunctions.generateIv(header.getHashAlgorithmEx(), header.getKeySalt(), kIntegrityValueBlock, blockSize);
Cipher cipher = CryptoFunctions.getCipher(getSecretKey(), header.getCipherAlgorithm(), header.getChainingMode(), iv, Cipher.ENCRYPT_MODE);
@@ -271,8 +273,8 @@ public class AgileEncryptor extends Encr
CTKeyEncryptor.Uri.HTTP_SCHEMAS_MICROSOFT_COM_OFFICE_2006_KEY_ENCRYPTOR_CERTIFICATE;
protected EncryptionDocument createEncryptionDocument() {
- AgileEncryptionVerifier ver = builder.getVerifier();
- AgileEncryptionHeader header = builder.getHeader();
+ AgileEncryptionVerifier ver = (AgileEncryptionVerifier)getEncryptionInfo().getVerifier();
+ AgileEncryptionHeader header = (AgileEncryptionHeader)getEncryptionInfo().getHeader();
EncryptionDocument ed = EncryptionDocument.Factory.newInstance();
CTEncryption edRoot = ed.addNewEncryption();
@@ -379,9 +381,10 @@ public class AgileEncryptor extends Encr
throws IOException, GeneralSecurityException {
DataSpaceMapUtils.addDefaultDataSpace(dir);
- final EncryptionInfo info = builder.getInfo();
+ final EncryptionInfo info = getEncryptionInfo();
EncryptionRecord er = new EncryptionRecord(){
+ @Override
public void write(LittleEndianByteArrayOutputStream bos) {
// EncryptionVersionInfo (4 bytes): A Version structure (section 2.1.4), where
// Version.vMajor MUST be 0x0004 and Version.vMinor MUST be 0x0004
@@ -422,7 +425,7 @@ public class AgileEncryptor extends Encr
@Override
protected Cipher initCipherForBlock(Cipher existing, int block, boolean lastChunk)
throws GeneralSecurityException {
- return AgileDecryptor.initCipherForBlock(existing, block, lastChunk, builder, getSecretKey(), Cipher.ENCRYPT_MODE);
+ return AgileDecryptor.initCipherForBlock(existing, block, lastChunk, getEncryptionInfo(), getSecretKey(), Cipher.ENCRYPT_MODE);
}
@Override
@@ -439,4 +442,11 @@ public class AgileEncryptor extends Encr
}
}
+ @Override
+ public AgileEncryptor clone() throws CloneNotSupportedException {
+ AgileEncryptor other = (AgileEncryptor)super.clone();
+ other.integritySalt = (integritySalt == null) ? null : integritySalt.clone();
+ other.pwHash = (pwHash == null) ? null : pwHash.clone();
+ return other;
+ }
}
Modified: poi/branches/hssf_cryptoapi/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestAgileEncryptionParameters.java
URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestAgileEncryptionParameters.java?rev=1755127&r1=1755126&r2=1755127&view=diff
==============================================================================
--- poi/branches/hssf_cryptoapi/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestAgileEncryptionParameters.java (original)
+++ poi/branches/hssf_cryptoapi/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestAgileEncryptionParameters.java Wed Aug 3 23:54:01 2016
@@ -16,8 +16,7 @@
==================================================================== */
package org.apache.poi.poifs.crypt;
-import static org.hamcrest.core.IsEqual.equalTo;
-import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertTrue;
import java.io.ByteArrayInputStream;
@@ -94,6 +93,7 @@ public class TestAgileEncryptionParamete
os.close();
bos.reset();
fsEnc.writeFilesystem(bos);
+ fsEnc.close();
POIFSFileSystem fsDec = new POIFSFileSystem(new ByteArrayInputStream(bos.toByteArray()));
EncryptionInfo infoDec = new EncryptionInfo(fsDec);
@@ -103,6 +103,7 @@ public class TestAgileEncryptionParamete
InputStream is = dec.getDataStream(fsDec);
byte actualData[] = IOUtils.toByteArray(is);
is.close();
- assertThat("Failed roundtrip - "+ca+"-"+ha+"-"+cm, testData, equalTo(actualData));
+ fsDec.close();
+ assertArrayEquals("Failed roundtrip - "+ca+"-"+ha+"-"+cm, testData, actualData);
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org