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 [1/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...
Author: kiwiwings
Date: Wed Aug 3 23:54:01 2016
New Revision: 1755127
URL: http://svn.apache.org/viewvc?rev=1755127&view=rev
Log:
Preparations for hssf_cryptoapi:
- Add cloneable
- Change existing hslf cryptoapi to streaming
Added:
poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIDocumentInputStream.java (with props)
poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIDocumentOutputStream.java (with props)
Modified:
poi/branches/hssf_cryptoapi/src/java/org/apache/poi/POIDocument.java
poi/branches/hssf_cryptoapi/src/java/org/apache/poi/hssf/record/RecordInputStream.java
poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/ChunkedCipherInputStream.java
poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/ChunkedCipherOutputStream.java
poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/Decryptor.java
poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/EncryptionHeader.java
poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/EncryptionInfo.java
poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/EncryptionInfoBuilder.java
poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/EncryptionVerifier.java
poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/Encryptor.java
poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4Decryptor.java
poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4EncryptionHeader.java
poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4EncryptionInfoBuilder.java
poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4EncryptionVerifier.java
poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4Encryptor.java
poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIDecryptor.java
poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptionHeader.java
poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptionInfoBuilder.java
poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptionVerifier.java
poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptor.java
poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/standard/StandardDecryptor.java
poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptionHeader.java
poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptionInfoBuilder.java
poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptionVerifier.java
poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/standard/StandardEncryptor.java
poi/branches/hssf_cryptoapi/src/java/org/apache/poi/util/LittleEndianByteArrayInputStream.java
poi/branches/hssf_cryptoapi/src/java/org/apache/poi/util/LittleEndianByteArrayOutputStream.java
poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileDecryptor.java
poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptionHeader.java
poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptionInfoBuilder.java
poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptionVerifier.java
poi/branches/hssf_cryptoapi/src/ooxml/java/org/apache/poi/poifs/crypt/agile/AgileEncryptor.java
poi/branches/hssf_cryptoapi/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestAgileEncryptionParameters.java
poi/branches/hssf_cryptoapi/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShowEncrypted.java
poi/branches/hssf_cryptoapi/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShowImpl.java
poi/branches/hssf_cryptoapi/src/scratchpad/testcases/org/apache/poi/hslf/record/TestDocumentEncryption.java
Modified: poi/branches/hssf_cryptoapi/src/java/org/apache/poi/POIDocument.java
URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/java/org/apache/poi/POIDocument.java?rev=1755127&r1=1755126&r2=1755127&view=diff
==============================================================================
--- poi/branches/hssf_cryptoapi/src/java/org/apache/poi/POIDocument.java (original)
+++ poi/branches/hssf_cryptoapi/src/java/org/apache/poi/POIDocument.java Wed Aug 3 23:54:01 2016
@@ -32,6 +32,7 @@ import org.apache.poi.hpsf.PropertySet;
import org.apache.poi.hpsf.PropertySetFactory;
import org.apache.poi.hpsf.SummaryInformation;
import org.apache.poi.poifs.crypt.EncryptionInfo;
+import org.apache.poi.poifs.crypt.cryptoapi.CryptoAPIDecryptor;
import org.apache.poi.poifs.filesystem.DirectoryNode;
import org.apache.poi.poifs.filesystem.DocumentInputStream;
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
@@ -59,6 +60,8 @@ public abstract class POIDocument implem
/* Have the property streams been read yet? (Only done on-demand) */
private boolean initialized = false;
+
+ private static final String[] encryptedStreamNames = { "EncryptedSummary" };
/**
* Constructs a POIDocument with the given directory node.
@@ -195,13 +198,18 @@ public abstract class POIDocument implem
try {
if (encryptionInfo != null) {
step = "getting encrypted";
- InputStream is = encryptionInfo.getDecryptor().getDataStream(directory);
- try {
- encPoifs = new NPOIFSFileSystem(is);
- dirNode = encPoifs.getRoot();
- } finally {
- is.close();
+ String encryptedStream = null;
+ for (String s : encryptedStreamNames) {
+ if (dirNode.hasEntry(s)) {
+ encryptedStream = s;
+ }
+ }
+ if (encryptedStream == null) {
+ throw new EncryptedDocumentException("can't find matching encrypted property stream");
}
+ CryptoAPIDecryptor dec = (CryptoAPIDecryptor)encryptionInfo.getDecryptor();
+ encPoifs = dec.getSummaryEntries(dirNode, encryptedStream);
+ dirNode = encPoifs.getRoot();
}
//directory can be null when creating new documents
Modified: poi/branches/hssf_cryptoapi/src/java/org/apache/poi/hssf/record/RecordInputStream.java
URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/java/org/apache/poi/hssf/record/RecordInputStream.java?rev=1755127&r1=1755126&r2=1755127&view=diff
==============================================================================
--- poi/branches/hssf_cryptoapi/src/java/org/apache/poi/hssf/record/RecordInputStream.java (original)
+++ poi/branches/hssf_cryptoapi/src/java/org/apache/poi/hssf/record/RecordInputStream.java Wed Aug 3 23:54:01 2016
@@ -18,13 +18,14 @@
package org.apache.poi.hssf.record;
import java.io.ByteArrayOutputStream;
+import java.io.IOException;
import java.io.InputStream;
import java.util.Locale;
import org.apache.poi.hssf.dev.BiffViewer;
import org.apache.poi.hssf.record.crypto.Biff8DecryptingStream;
import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
-import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.Internal;
import org.apache.poi.util.LittleEndianConsts;
import org.apache.poi.util.LittleEndianInput;
import org.apache.poi.util.LittleEndianInputStream;
@@ -91,6 +92,10 @@ public final class RecordInputStream imp
* index within the data section of the current BIFF record
*/
private int _currentDataOffset;
+ /**
+ * index within the data section when mark() was called
+ */
+ private int _markedDataOffset;
private static final class SimpleHeaderInput implements BiffHeaderInput {
@@ -123,8 +128,8 @@ public final class RecordInputStream imp
_bhi = new SimpleHeaderInput(in);
} else {
Biff8DecryptingStream bds = new Biff8DecryptingStream(in, initialOffset, key);
+ _dataInput = bds;
_bhi = bds;
- _dataInput = bds;
}
_nextSid = readNextSid();
}
@@ -491,4 +496,31 @@ public final class RecordInputStream imp
public int getNextSid() {
return _nextSid;
}
+
+ /**
+ * Mark the stream position - experimental function
+ *
+ * @param readlimit the read ahead limit
+ *
+ * @see InputStream#mark(int)
+ */
+ @Internal
+ public void mark(int readlimit) {
+ ((InputStream)_dataInput).mark(readlimit);
+ _markedDataOffset = _currentDataOffset;
+ }
+
+ /**
+ * Resets the stream position to the previously marked position.
+ * Experimental function - this only works, when nextRecord() wasn't called in the meantime.
+ *
+ * @throws IOException if marking is not supported
+ *
+ * @see InputStream#reset()
+ */
+ @Internal
+ public void reset() throws IOException {
+ ((InputStream)_dataInput).reset();
+ _currentDataOffset = _markedDataOffset;
+ }
}
Modified: poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/ChunkedCipherInputStream.java
URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/ChunkedCipherInputStream.java?rev=1755127&r1=1755126&r2=1755127&view=diff
==============================================================================
--- poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/ChunkedCipherInputStream.java (original)
+++ poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/ChunkedCipherInputStream.java Wed Aug 3 23:54:01 2016
@@ -16,6 +16,7 @@
==================================================================== */
package org.apache.poi.poifs.crypt;
+import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
@@ -29,54 +30,81 @@ import org.apache.poi.util.LittleEndianI
@Internal
public abstract class ChunkedCipherInputStream extends LittleEndianInputStream {
- private final int chunkSize;
- private final int chunkMask;
- private final int chunkBits;
-
- private int _lastIndex = 0;
- private long _pos = 0;
- private long _size;
- private byte[] _chunk;
- private Cipher _cipher;
+ private final int _chunkSize;
+ private final int _chunkBits;
+
+ private final long _size;
+ private final byte[] _chunk;
+ private final Cipher _cipher;
+
+ private int _lastIndex;
+ private long _pos;
+ private boolean _chunkIsValid = false;
public ChunkedCipherInputStream(LittleEndianInput stream, long size, int chunkSize)
- throws GeneralSecurityException {
+ throws GeneralSecurityException {
+ this(stream, size, chunkSize, 0);
+ }
+
+ public ChunkedCipherInputStream(LittleEndianInput stream, long size, int chunkSize, int initialPos)
+ throws GeneralSecurityException {
super((InputStream)stream);
_size = size;
- this.chunkSize = chunkSize;
- chunkMask = chunkSize-1;
- chunkBits = Integer.bitCount(chunkMask);
+ _pos = initialPos;
+ this._chunkSize = chunkSize;
+ if (chunkSize == -1) {
+ _chunk = new byte[4096];
+ } else {
+ _chunk = new byte[chunkSize];
+ }
+ _chunkBits = Integer.bitCount(_chunk.length-1);
+ _lastIndex = (int)(_pos >> _chunkBits);
+ _cipher = initCipherForBlock(null, _lastIndex);
+ }
+
+ public final Cipher initCipherForBlock(int block) throws IOException, GeneralSecurityException {
+ if (_chunkSize != -1) {
+ throw new GeneralSecurityException("the cipher block can only be set for streaming encryption, e.g. CryptoAPI...");
+ }
- _cipher = initCipherForBlock(null, 0);
+ _chunkIsValid = false;
+ return initCipherForBlock(_cipher, block);
}
protected abstract Cipher initCipherForBlock(Cipher existing, int block)
throws GeneralSecurityException;
+ @Override
public int read() throws IOException {
byte[] b = new byte[1];
- if (read(b) == 1)
+ if (read(b) == 1) {
return b[0];
+ }
return -1;
}
// do not implement! -> recursion
// public int read(byte[] b) throws IOException;
+ @Override
public int read(byte[] b, int off, int len) throws IOException {
int total = 0;
- if (available() <= 0) return -1;
+ if (available() <= 0) {
+ return -1;
+ }
+ final int chunkMask = getChunkMask();
while (len > 0) {
- if (_chunk == null) {
+ if (!_chunkIsValid) {
try {
- _chunk = nextChunk();
+ nextChunk();
+ _chunkIsValid = true;
} catch (GeneralSecurityException e) {
throw new EncryptedDocumentException(e.getMessage(), e);
}
}
- int count = (int)(chunkSize - (_pos & chunkMask));
+ int count = (int)(_chunk.length - (_pos & chunkMask));
int avail = available();
if (avail == 0) {
return total;
@@ -86,8 +114,9 @@ public abstract class ChunkedCipherInput
off += count;
len -= count;
_pos += count;
- if ((_pos & chunkMask) == 0)
- _chunk = null;
+ if ((_pos & chunkMask) == 0) {
+ _chunkIsValid = false;
+ }
total += count;
}
@@ -95,18 +124,28 @@ public abstract class ChunkedCipherInput
}
@Override
- public long skip(long n) throws IOException {
+ public long skip(final long n) throws IOException {
long start = _pos;
- long skip = Math.min(available(), n);
+ long skip = Math.min(remainingBytes(), n);
- if ((((_pos + skip) ^ start) & ~chunkMask) != 0)
- _chunk = null;
+ if ((((_pos + skip) ^ start) & ~getChunkMask()) != 0) {
+ _chunkIsValid = false;
+ }
_pos += skip;
return skip;
}
@Override
public int available() {
+ return remainingBytes();
+ }
+
+ /**
+ * Helper method for forbidden available call - we know the size beforehand, so it's ok ...
+ *
+ * @return the remaining byte until EOF
+ */
+ private int remainingBytes() {
return (int)(_size - _pos);
}
@@ -125,17 +164,37 @@ public abstract class ChunkedCipherInput
throw new UnsupportedOperationException();
}
- private byte[] nextChunk() throws GeneralSecurityException, IOException {
- int index = (int)(_pos >> chunkBits);
- initCipherForBlock(_cipher, index);
+ private int getChunkMask() {
+ return _chunk.length-1;
+ }
+
+ private void nextChunk() throws GeneralSecurityException, IOException {
+ if (_chunkSize != -1) {
+ int index = (int)(_pos >> _chunkBits);
+ initCipherForBlock(_cipher, index);
- if (_lastIndex != index) {
- super.skip((index - _lastIndex) << chunkBits);
+ if (_lastIndex != index) {
+ super.skip((index - _lastIndex) << _chunkBits);
+ }
+
+ _lastIndex = index + 1;
}
- byte[] block = new byte[Math.min(super.available(), chunkSize)];
- super.read(block, 0, block.length);
- _lastIndex = index + 1;
- return _cipher.doFinal(block);
+ final int todo = (int)Math.min(_size, _chunk.length);
+ int readBytes = 0, totalBytes = 0;
+ do {
+ readBytes = super.read(_chunk, totalBytes, todo-totalBytes);
+ totalBytes += Math.max(0, readBytes);
+ } while (readBytes != -1 && totalBytes < todo);
+
+ if (readBytes == -1 && _pos+totalBytes < _size) {
+ throw new EOFException("buffer underrun");
+ }
+
+ if (_chunkSize == -1) {
+ _cipher.update(_chunk, 0, totalBytes, _chunk);
+ } else {
+ _cipher.doFinal(_chunk, 0, totalBytes, _chunk);
+ }
}
}
Modified: poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/ChunkedCipherOutputStream.java
URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/ChunkedCipherOutputStream.java?rev=1755127&r1=1755126&r2=1755127&view=diff
==============================================================================
--- poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/ChunkedCipherOutputStream.java (original)
+++ poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/ChunkedCipherOutputStream.java Wed Aug 3 23:54:01 2016
@@ -32,6 +32,7 @@ import org.apache.poi.EncryptedDocumentE
import org.apache.poi.poifs.filesystem.DirectoryNode;
import org.apache.poi.poifs.filesystem.POIFSWriterEvent;
import org.apache.poi.poifs.filesystem.POIFSWriterListener;
+import org.apache.poi.util.IOUtils;
import org.apache.poi.util.Internal;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianConsts;
@@ -41,137 +42,177 @@ import org.apache.poi.util.TempFile;
@Internal
public abstract class ChunkedCipherOutputStream extends FilterOutputStream {
- private static final POILogger logger = POILogFactory.getLogger(ChunkedCipherOutputStream.class);
-
- protected final int chunkSize;
- protected final int chunkMask;
- protected final int chunkBits;
-
+ private static final POILogger LOG = POILogFactory.getLogger(ChunkedCipherOutputStream.class);
+ private static final int STREAMING = -1;
+
+ protected final int _chunkSize;
+ protected final int _chunkBits;
+
private final byte[] _chunk;
- private final File fileOut;
- private final DirectoryNode dir;
+ private final File _fileOut;
+ private final DirectoryNode _dir;
private long _pos = 0;
private Cipher _cipher;
-
+
public ChunkedCipherOutputStream(DirectoryNode dir, int chunkSize) throws IOException, GeneralSecurityException {
super(null);
- this.chunkSize = chunkSize;
- chunkMask = chunkSize-1;
- chunkBits = Integer.bitCount(chunkMask);
- _chunk = new byte[chunkSize];
-
- fileOut = TempFile.createTempFile("encrypted_package", "crypt");
- fileOut.deleteOnExit();
- this.out = new FileOutputStream(fileOut);
- this.dir = dir;
+ this._chunkSize = chunkSize;
+ int cs = chunkSize == STREAMING ? 4096 : chunkSize;
+ _chunk = new byte[cs];
+ _chunkBits = Integer.bitCount(cs-1);
+ _fileOut = TempFile.createTempFile("encrypted_package", "crypt");
+ _fileOut.deleteOnExit();
+ this.out = new FileOutputStream(_fileOut);
+ this._dir = dir;
+ _cipher = initCipherForBlock(null, 0, false);
+ }
+
+ public ChunkedCipherOutputStream(OutputStream stream, int chunkSize) throws IOException, GeneralSecurityException {
+ super(stream);
+ this._chunkSize = chunkSize;
+ int cs = chunkSize == STREAMING ? 4096 : chunkSize;
+ _chunk = new byte[cs];
+ _chunkBits = Integer.bitCount(cs-1);
+ _fileOut = null;
+ _dir = null;
_cipher = initCipherForBlock(null, 0, false);
}
+ public final Cipher initCipherForBlock(int block, boolean lastChunk) throws IOException, GeneralSecurityException {
+ return initCipherForBlock(_cipher, block, lastChunk);
+ }
+
protected abstract Cipher initCipherForBlock(Cipher existing, int block, boolean lastChunk)
- throws GeneralSecurityException;
-
- @SuppressWarnings("hiding")
+ throws IOException, GeneralSecurityException;
+
protected abstract void calculateChecksum(File fileOut, int oleStreamSize)
throws GeneralSecurityException, IOException;
-
- @SuppressWarnings("hiding")
+
protected abstract void createEncryptionInfoEntry(DirectoryNode dir, File tmpFile)
throws IOException, GeneralSecurityException;
+ @Override
public void write(int b) throws IOException {
write(new byte[]{(byte)b});
}
+ @Override
public void write(byte[] b) throws IOException {
write(b, 0, b.length);
}
+ @Override
public void write(byte[] b, int off, int len)
throws IOException {
- if (len == 0) return;
-
+ if (len == 0) {
+ return;
+ }
+
if (len < 0 || b.length < off+len) {
throw new IOException("not enough bytes in your input buffer");
}
-
+
+ final int chunkMask = getChunkMask();
while (len > 0) {
int posInChunk = (int)(_pos & chunkMask);
- int nextLen = Math.min(chunkSize-posInChunk, len);
+ int nextLen = Math.min(_chunk.length-posInChunk, len);
System.arraycopy(b, off, _chunk, posInChunk, nextLen);
_pos += nextLen;
off += nextLen;
len -= nextLen;
if ((_pos & chunkMask) == 0) {
- try {
- writeChunk();
- } catch (GeneralSecurityException e) {
- throw new IOException(e);
- }
+ writeChunk(len > 0);
}
}
}
- protected void writeChunk() throws IOException, GeneralSecurityException {
- int posInChunk = (int)(_pos & chunkMask);
+ private int getChunkMask() {
+ return _chunk.length-1;
+ }
+
+ protected void writeChunk(boolean continued) throws IOException {
+ if (_pos == 0) {
+ return;
+ }
+
+ int posInChunk = (int)(_pos & getChunkMask());
+
// normally posInChunk is 0, i.e. on the next chunk (-> index-1)
// but if called on close(), posInChunk is somewhere within the chunk data
- int index = (int)(_pos >> chunkBits);
+ int index = (int)(_pos >> _chunkBits);
boolean lastChunk;
if (posInChunk==0) {
index--;
- posInChunk = chunkSize;
+ posInChunk = _chunk.length;
lastChunk = false;
} else {
// pad the last chunk
lastChunk = true;
}
- _cipher = initCipherForBlock(_cipher, index, lastChunk);
+ int ciLen;
+ try {
+ if (_chunkSize == STREAMING) {
+ if (continued) {
+ ciLen = _cipher.update(_chunk, 0, posInChunk, _chunk);
+ } else {
+ ciLen = _cipher.doFinal(_chunk, 0, posInChunk, _chunk);
+ }
+
+ // reset stream (not only) in case we were interrupted by plain stream parts
+ _pos = 0;
+ } else {
+ _cipher = initCipherForBlock(_cipher, index, lastChunk);
+ ciLen = _cipher.doFinal(_chunk, 0, posInChunk, _chunk);
+ }
+ } catch (GeneralSecurityException e) {
+ throw new IOException("can't re-/initialize cipher", e);
+ }
- int ciLen = _cipher.doFinal(_chunk, 0, posInChunk, _chunk);
out.write(_chunk, 0, ciLen);
}
-
+
+ @Override
public void close() throws IOException {
try {
- writeChunk();
+ writeChunk(false);
super.close();
-
- int oleStreamSize = (int)(fileOut.length()+LittleEndianConsts.LONG_SIZE);
- calculateChecksum(fileOut, (int)_pos);
- dir.createDocument(DEFAULT_POIFS_ENTRY, oleStreamSize, new EncryptedPackageWriter());
- createEncryptionInfoEntry(dir, fileOut);
+
+ if (_fileOut != null) {
+ int oleStreamSize = (int)(_fileOut.length()+LittleEndianConsts.LONG_SIZE);
+ calculateChecksum(_fileOut, (int)_pos);
+ _dir.createDocument(DEFAULT_POIFS_ENTRY, oleStreamSize, new EncryptedPackageWriter());
+ createEncryptionInfoEntry(_dir, _fileOut);
+ }
} catch (GeneralSecurityException e) {
throw new IOException(e);
}
}
private class EncryptedPackageWriter implements POIFSWriterListener {
+ @Override
public void processPOIFSWriterEvent(POIFSWriterEvent event) {
try {
OutputStream os = event.getStream();
- byte buf[] = new byte[chunkSize];
-
- // StreamSize (8 bytes): An unsigned integer that specifies the number of bytes used by data
- // encrypted within the EncryptedData field, not including the size of the StreamSize field.
- // Note that the actual size of the \EncryptedPackage stream (1) can be larger than this
+
+ // StreamSize (8 bytes): An unsigned integer that specifies the number of bytes used by data
+ // encrypted within the EncryptedData field, not including the size of the StreamSize field.
+ // Note that the actual size of the \EncryptedPackage stream (1) can be larger than this
// value, depending on the block size of the chosen encryption algorithm
+ byte buf[] = new byte[LittleEndianConsts.LONG_SIZE];
LittleEndian.putLong(buf, 0, _pos);
- os.write(buf, 0, LittleEndian.LONG_SIZE);
+ os.write(buf);
- FileInputStream fis = new FileInputStream(fileOut);
- int readBytes;
- while ((readBytes = fis.read(buf)) != -1) {
- os.write(buf, 0, readBytes);
- }
+ FileInputStream fis = new FileInputStream(_fileOut);
+ IOUtils.copy(fis, os);
fis.close();
os.close();
-
- if (!fileOut.delete()) {
- logger.log(POILogger.ERROR, "Can't delete temporary encryption file: "+fileOut);
+
+ if (!_fileOut.delete()) {
+ LOG.log(POILogger.ERROR, "Can't delete temporary encryption file: "+_fileOut);
}
} catch (IOException e) {
throw new EncryptedDocumentException(e);
Modified: poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/Decryptor.java
URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/Decryptor.java?rev=1755127&r1=1755126&r2=1755127&view=diff
==============================================================================
--- poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/Decryptor.java (original)
+++ poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/Decryptor.java Wed Aug 3 23:54:01 2016
@@ -20,24 +20,26 @@ import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
+import javax.crypto.Cipher;
import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
import org.apache.poi.EncryptedDocumentException;
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;
+import org.apache.poi.util.LittleEndianInput;
-public abstract class Decryptor {
+public abstract class Decryptor implements Cloneable {
public static final String DEFAULT_PASSWORD="VelvetSweatshop";
public static final String DEFAULT_POIFS_ENTRY="EncryptedPackage";
- protected final EncryptionInfoBuilder builder;
+ protected EncryptionInfo encryptionInfo;
private SecretKey secretKey;
private byte[] verifier, integrityHmacKey, integrityHmacValue;
- protected Decryptor(EncryptionInfoBuilder builder) {
- this.builder = builder;
+ protected Decryptor() {
}
/**
@@ -54,6 +56,45 @@ public abstract class Decryptor {
public abstract InputStream getDataStream(DirectoryNode dir)
throws IOException, GeneralSecurityException;
+ /**
+ * Wraps a stream for decryption<p>
+ *
+ * As we are handling streams and don't know the total length beforehand,
+ * it's the callers duty to care for the length of the entries.
+ *
+ * @param stream the stream to be wrapped
+ * @param initialPos initial/current byte position within the stream
+ * @return decrypted stream
+ */
+ public InputStream getDataStream(LittleEndianInput stream, int size, int initialPos)
+ throws IOException, GeneralSecurityException {
+ throw new RuntimeException("this decryptor doesn't support reading from a stream");
+ }
+
+ /**
+ * 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");
+ }
+
+ /**
+ * Initializes a cipher object for a given block index for encryption
+ *
+ * @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
+ */
+ public Cipher initCipherForBlock(Cipher cipher, int block)
+ throws GeneralSecurityException {
+ throw new RuntimeException("this decryptor doesn't support initCipherForBlock");
+ }
+
public abstract boolean verifyPassword(String password)
throws GeneralSecurityException;
@@ -85,9 +126,11 @@ public abstract class Decryptor {
public InputStream getDataStream(NPOIFSFileSystem fs) throws IOException, GeneralSecurityException {
return getDataStream(fs.getRoot());
}
+
public InputStream getDataStream(OPOIFSFileSystem fs) throws IOException, GeneralSecurityException {
return getDataStream(fs.getRoot());
}
+
public InputStream getDataStream(POIFSFileSystem fs) throws IOException, GeneralSecurityException {
return getDataStream(fs.getRoot());
}
@@ -126,10 +169,29 @@ public abstract class Decryptor {
}
protected int getBlockSizeInBytes() {
- return builder.getHeader().getBlockSize();
+ return encryptionInfo.getHeader().getBlockSize();
}
protected int getKeySizeInBytes() {
- return builder.getHeader().getKeySize()/8;
+ return encryptionInfo.getHeader().getKeySize()/8;
+ }
+
+ public EncryptionInfo getEncryptionInfo() {
+ return encryptionInfo;
+ }
+
+ public void setEncryptionInfo(EncryptionInfo encryptionInfo) {
+ this.encryptionInfo = encryptionInfo;
+ }
+
+ @Override
+ public Decryptor clone() throws CloneNotSupportedException {
+ Decryptor other = (Decryptor)super.clone();
+ other.integrityHmacKey = integrityHmacKey.clone();
+ other.integrityHmacValue = integrityHmacValue.clone();
+ other.verifier = verifier.clone();
+ other.secretKey = new SecretKeySpec(secretKey.getEncoded(), secretKey.getAlgorithm());
+ // encryptionInfo is set from outside
+ return other;
}
}
\ No newline at end of file
Modified: poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/EncryptionHeader.java
URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/EncryptionHeader.java?rev=1755127&r1=1755126&r2=1755127&view=diff
==============================================================================
--- poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/EncryptionHeader.java (original)
+++ poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/EncryptionHeader.java Wed Aug 3 23:54:01 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/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/EncryptionInfo.java
URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/EncryptionInfo.java?rev=1755127&r1=1755126&r2=1755127&view=diff
==============================================================================
--- poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/EncryptionInfo.java (original)
+++ poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/EncryptionInfo.java Wed Aug 3 23:54:01 2016
@@ -34,15 +34,15 @@ import org.apache.poi.util.LittleEndianI
/**
*/
-public class EncryptionInfo {
+public class EncryptionInfo implements Cloneable {
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
@@ -96,11 +96,10 @@ public class EncryptionInfo {
public EncryptionInfo(LittleEndianInput dis, boolean isCryptoAPI) throws IOException {
final EncryptionMode encryptionMode;
- versionMajor = dis.readShort();
- versionMinor = dis.readShort();
+ versionMajor = dis.readUShort();
+ versionMinor = dis.readUShort();
- if (!isCryptoAPI
- && versionMajor == binaryRC4.versionMajor
+ if ( versionMajor == binaryRC4.versionMajor
&& versionMinor == binaryRC4.versionMinor) {
encryptionMode = binaryRC4;
encryptionFlags = -1;
@@ -138,10 +137,6 @@ public class EncryptionInfo {
}
eib.initialize(this, dis);
- header = eib.getHeader();
- verifier = eib.getVerifier();
- decryptor = eib.getDecryptor();
- encryptor = eib.getEncryptor();
}
/**
@@ -187,11 +182,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 +219,32 @@ 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;
+ }
+
+ @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/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/EncryptionInfoBuilder.java
URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/EncryptionInfoBuilder.java?rev=1755127&r1=1755126&r2=1755127&view=diff
==============================================================================
--- poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/EncryptionInfoBuilder.java (original)
+++ poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/EncryptionInfoBuilder.java Wed Aug 3 23:54:01 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/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/EncryptionVerifier.java
URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/EncryptionVerifier.java?rev=1755127&r1=1755126&r2=1755127&view=diff
==============================================================================
--- poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/EncryptionVerifier.java (original)
+++ poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/EncryptionVerifier.java Wed Aug 3 23:54:01 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/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/Encryptor.java
URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/Encryptor.java?rev=1755127&r1=1755126&r2=1755127&view=diff
==============================================================================
--- poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/Encryptor.java (original)
+++ poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/Encryptor.java Wed Aug 3 23:54:01 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;
/**
@@ -66,4 +68,20 @@ public abstract class Encryptor {
protected void setSecretKey(SecretKey secretKey) {
this.secretKey = secretKey;
}
+
+ public EncryptionInfo getEncryptionInfo() {
+ return encryptionInfo;
+ }
+
+ public void setEncryptionInfo(EncryptionInfo encryptionInfo) {
+ this.encryptionInfo = encryptionInfo;
+ }
+
+ @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/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4Decryptor.java
URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4Decryptor.java?rev=1755127&r1=1755126&r2=1755127&view=diff
==============================================================================
--- poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4Decryptor.java (original)
+++ poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4Decryptor.java Wed Aug 3 23:54:01 2016
@@ -29,36 +29,45 @@ import javax.crypto.spec.SecretKeySpec;
import org.apache.poi.EncryptedDocumentException;
import org.apache.poi.poifs.crypt.*;
+import org.apache.poi.poifs.crypt.cryptoapi.CryptoAPIDecryptor;
import org.apache.poi.poifs.filesystem.DirectoryNode;
import org.apache.poi.poifs.filesystem.DocumentInputStream;
import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.LittleEndianInput;
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(LittleEndianInput 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 +87,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 +111,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 +131,22 @@ 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);
+ }
+
+ public InputStream getDataStream(LittleEndianInput stream)
+ throws IOException, GeneralSecurityException {
+ return new BinaryRC4CipherInputStream(stream);
}
+
+ @Override
public long getLength() {
if (_length == -1L) {
throw new IllegalStateException("Decryptor.getDataStream() was not called");
@@ -132,4 +154,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/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4EncryptionHeader.java
URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4EncryptionHeader.java?rev=1755127&r1=1755126&r2=1755127&view=diff
==============================================================================
--- poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4EncryptionHeader.java (original)
+++ poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4EncryptionHeader.java Wed Aug 3 23:54:01 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/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4EncryptionInfoBuilder.java
URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4EncryptionInfoBuilder.java?rev=1755127&r1=1755126&r2=1755127&view=diff
==============================================================================
--- poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4EncryptionInfoBuilder.java (original)
+++ poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4EncryptionInfoBuilder.java Wed Aug 3 23:54:01 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/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4EncryptionVerifier.java
URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4EncryptionVerifier.java?rev=1755127&r1=1755126&r2=1755127&view=diff
==============================================================================
--- poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4EncryptionVerifier.java (original)
+++ poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4EncryptionVerifier.java Wed Aug 3 23:54:01 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/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4Encryptor.java
URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4Encryptor.java?rev=1755127&r1=1755126&r2=1755127&view=diff
==============================================================================
--- poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4Encryptor.java (original)
+++ poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/binaryrc4/BinaryRC4Encryptor.java Wed Aug 3 23:54:01 2016
@@ -34,39 +34,17 @@ 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;
-
- 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 +54,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,6 +77,7 @@ public class BinaryRC4Encryptor extends
}
}
+ @Override
public OutputStream getDataStream(DirectoryNode dir)
throws IOException, GeneralSecurityException {
OutputStream countStream = new BinaryRC4CipherOutputStream(dir);
@@ -106,15 +85,16 @@ public class BinaryRC4Encryptor extends
}
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 +104,33 @@ public class BinaryRC4Encryptor extends
};
DataSpaceMapUtils.createEncryptionEntry(dir, "EncryptionInfo", er);
}
+
+ @Override
+ public BinaryRC4Encryptor clone() throws CloneNotSupportedException {
+ return (BinaryRC4Encryptor)super.clone();
+ }
+
+ protected class BinaryRC4CipherOutputStream extends ChunkedCipherOutputStream {
+
+ @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);
+ }
+
+ public BinaryRC4CipherOutputStream(DirectoryNode dir)
+ throws IOException, GeneralSecurityException {
+ super(dir, 512);
+ }
+ }
}
Modified: poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIDecryptor.java
URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIDecryptor.java?rev=1755127&r1=1755126&r2=1755127&view=diff
==============================================================================
--- poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIDecryptor.java (original)
+++ poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIDecryptor.java Wed Aug 3 23:54:01 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,79 +26,34 @@ 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;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.LittleEndianInput;
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 +65,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 +94,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 +139,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(LittleEndianInput 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 +158,17 @@ public class CryptoAPIDecryptor extends
*
* @see <a href="http://msdn.microsoft.com/en-us/library/dd943321(v=office.12).aspx">2.3.5.4 RC4 CryptoAPI Encrypted Summary Stream</a>
*/
- public InputStream getDataStream(DirectoryNode dir)
+ public POIFSFileSystem getSummaryEntries(DirectoryNode root, String encryptedStream)
throws IOException, GeneralSecurityException {
- NPOIFSFileSystem fsOut = new NPOIFSFileSystem();
- DocumentNode es = (DocumentNode) dir.getEntry("EncryptedSummary");
- DocumentInputStream dis = dir.createDocumentInputStream(es);
+ POIFSFileSystem fsOut = new POIFSFileSystem();
+ // HSLF: encryptedStream
+ // HSSF: encryption
+ DocumentNode es = (DocumentNode) root.getEntry(encryptedStream);
+ DocumentInputStream dis = root.createDocumentInputStream(es);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
IOUtils.copy(dis, bos);
dis.close();
- SeekableByteArrayInputStream sbis = new SeekableByteArrayInputStream(bos.toByteArray());
+ CryptoAPIDocumentInputStream sbis = new CryptoAPIDocumentInputStream(this, bos.toByteArray());
LittleEndianInputStream leis = new LittleEndianInputStream(sbis);
int streamDescriptorArrayOffset = (int) leis.readUInt();
/* int streamDescriptorArraySize = (int) */ leis.readUInt();
@@ -239,21 +202,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(LittleEndianInput stream, long size, int initialPos)
+ throws GeneralSecurityException {
+ super(stream, size, _chunkSize, initialPos);
+ }
+ }
}
Added: poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIDocumentInputStream.java
URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIDocumentInputStream.java?rev=1755127&view=auto
==============================================================================
--- poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIDocumentInputStream.java (added)
+++ poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIDocumentInputStream.java Wed Aug 3 23:54:01 2016
@@ -0,0 +1,86 @@
+/* ====================================================================
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+==================================================================== */
+package org.apache.poi.poifs.crypt.cryptoapi;
+
+import java.io.ByteArrayInputStream;
+import java.security.GeneralSecurityException;
+
+import javax.crypto.Cipher;
+import javax.crypto.ShortBufferException;
+
+import org.apache.poi.EncryptedDocumentException;
+import org.apache.poi.util.Internal;
+
+/**
+ * A seekable InputStream, which is used to decrypt/extract the document entries
+ * within the encrypted stream
+ */
+@Internal
+/* package */ class CryptoAPIDocumentInputStream extends ByteArrayInputStream {
+ private Cipher cipher;
+ private final CryptoAPIDecryptor decryptor;
+ private 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 = decryptor.initCipherForBlock(cipher, block);
+ }
+
+ @Override
+ 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];
+ }
+
+ @Override
+ 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 CryptoAPIDocumentInputStream(CryptoAPIDecryptor decryptor, byte buf[])
+ throws GeneralSecurityException {
+ super(buf);
+ this.decryptor = decryptor;
+ cipher = decryptor.initCipherForBlock(null, 0);
+ }
+}
\ No newline at end of file
Propchange: poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIDocumentInputStream.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIDocumentOutputStream.java
URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIDocumentOutputStream.java?rev=1755127&view=auto
==============================================================================
--- poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIDocumentOutputStream.java (added)
+++ poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIDocumentOutputStream.java Wed Aug 3 23:54:01 2016
@@ -0,0 +1,74 @@
+/* ====================================================================
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+==================================================================== */
+package org.apache.poi.poifs.crypt.cryptoapi;
+
+import java.io.ByteArrayOutputStream;
+import java.security.GeneralSecurityException;
+
+import javax.crypto.Cipher;
+
+import org.apache.poi.EncryptedDocumentException;
+import org.apache.poi.util.Internal;
+
+/**
+ * An OutputStream for the document entries within the encrypted stream
+ */
+@Internal
+/* package */ class CryptoAPIDocumentOutputStream extends ByteArrayOutputStream {
+ private Cipher cipher;
+ private CryptoAPIEncryptor encryptor;
+ private byte oneByte[] = { 0 };
+
+ public CryptoAPIDocumentOutputStream(CryptoAPIEncryptor encryptor) throws GeneralSecurityException {
+ this.encryptor = encryptor;
+ setBlock(0);
+ }
+
+ public byte[] getBuf() {
+ return buf;
+ }
+
+ public void setSize(int count) {
+ this.count = count;
+ }
+
+ public void setBlock(int block) throws GeneralSecurityException {
+ cipher = encryptor.initCipherForBlock(cipher, block);
+ }
+
+ @Override
+ 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
+ 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);
+ }
+ }
+
+}
\ No newline at end of file
Propchange: poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIDocumentOutputStream.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptionHeader.java
URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptionHeader.java?rev=1755127&r1=1755126&r2=1755127&view=diff
==============================================================================
--- poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptionHeader.java (original)
+++ poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptionHeader.java Wed Aug 3 23:54:01 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/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptionInfoBuilder.java
URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptionInfoBuilder.java?rev=1755127&r1=1755126&r2=1755127&view=diff
==============================================================================
--- poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptionInfoBuilder.java (original)
+++ poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptionInfoBuilder.java Wed Aug 3 23:54:01 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/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptionVerifier.java
URL: http://svn.apache.org/viewvc/poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptionVerifier.java?rev=1755127&r1=1755126&r2=1755127&view=diff
==============================================================================
--- poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptionVerifier.java (original)
+++ poi/branches/hssf_cryptoapi/src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptionVerifier.java Wed Aug 3 23:54:01 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();
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org