ASF Bugzilla – Attachment 24105 Details for
Bug 47652
[PATCH] Initial support for encrypted workbooks
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
patch
crypto.patch (text/plain), 8.43 KB, created by
Maxim Valyanskiy
on 2009-08-06 02:57:53 UTC
(
hide
)
Description:
patch
Filename:
MIME Type:
Creator:
Maxim Valyanskiy
Created:
2009-08-06 02:57:53 UTC
Size:
8.43 KB
patch
obsolete
>Index: src/java/org/apache/poi/hssf/record/RecordInputStream.java >=================================================================== >--- src/java/org/apache/poi/hssf/record/RecordInputStream.java (revision 801584) >+++ src/java/org/apache/poi/hssf/record/RecordInputStream.java (working copy) >@@ -19,12 +19,18 @@ > > import java.io.ByteArrayOutputStream; > import java.io.InputStream; >+import java.util.Set; >+import java.util.Collections; >+import java.util.HashSet; > > import org.apache.poi.hssf.dev.BiffViewer; > import org.apache.poi.util.LittleEndian; > import org.apache.poi.util.LittleEndianInput; > import org.apache.poi.util.LittleEndianInputStream; >+import org.apache.poi.util.RC4InputStream; > >+import javax.crypto.Cipher; >+ > /** > * Title: Record Input Stream<P> > * Description: Wraps a stream and provides helper methods for the construction of records.<P> >@@ -41,8 +47,26 @@ > */ > private static final int DATA_LEN_NEEDS_TO_BE_READ = -1; > private static final byte[] EMPTY_BYTE_ARRAY = { }; >- >- /** >+ >+ private RC4InputStream rc4is; >+ >+ private static final Set<Short> unencryptSid = new HashSet<Short>(); >+ static { >+ /* >+ [MS-XLS] â v20090708 >+ Excel Binary File Format (.xls) Structure Specification >+ */ >+ unencryptSid.add(BOFRecord.sid); >+ unencryptSid.add(FilePassRecord.sid); >+ // UsrExcl >+ // FileLock >+ unencryptSid.add(InterfaceHdrRecord.sid); >+ // RRDInfo >+ // RRDHead >+ // TODO: Additionally, the lbPlyPos field of the BoundSheet8 record MUST NOT be encrypted. >+ } >+ >+ /** > * For use in {@link BiffViewer} which may construct {@link Record}s that don't completely > * read all available data. This exception should never be thrown otherwise. > */ >@@ -77,13 +101,8 @@ > private int _currentDataOffset; > > public RecordInputStream(InputStream in) throws RecordFormatException { >- if (in instanceof LittleEndianInput) { >- // accessing directly is an optimisation >- _le = (LittleEndianInput) in; >- } else { >- // less optimal, but should work OK just the same. Often occurs in junit tests. >- _le = new LittleEndianInputStream(in); >- } >+ rc4is = new RC4InputStream(in); >+ _le = new LittleEndianInputStream(rc4is); > _nextSid = readNextSid(); > } > >@@ -100,6 +119,7 @@ > _currentDataOffset += LittleEndian.BYTE_SIZE; > return _le.readUByte(); > } >+ > public int read(byte[] b, int off, int len) { > int limit = Math.min(len, remaining()); > if (limit == 0) { >@@ -143,6 +163,7 @@ > } > return INVALID_SID_VALUE; > } >+ rc4is.setDecrypt(false); > int result = _le.readUShort(); > if (result == INVALID_SID_VALUE) { > throw new RecordFormatException("Found invalid sid (" + result + ")"); >@@ -169,6 +190,10 @@ > throw new RecordFormatException("The content of an excel record cannot exceed " > + MAX_RECORD_DATA_SIZE + " bytes"); > } >+ >+ if (!unencryptSid.contains((short) _currentSid)) { >+ rc4is.setDecrypt(true); >+ } > } > > private void checkRecordPosition(int requiredByteCount) { >@@ -394,4 +419,8 @@ > // and before the formatting run data) > return _nextSid == ContinueRecord.sid; > } >+ >+ public void setRC4Header(RC4Header rc4Header) { >+ rc4is.setHeader(rc4Header); >+ } > } >Index: src/java/org/apache/poi/hssf/record/RecordFactoryInputStream.java >=================================================================== >--- src/java/org/apache/poi/hssf/record/RecordFactoryInputStream.java (revision 801584) >+++ src/java/org/apache/poi/hssf/record/RecordFactoryInputStream.java (working copy) >@@ -148,6 +148,10 @@ > return record; > } > >+ if (record instanceof FilePassRecord) { >+ recStream.setRC4Header(((FilePassRecord) record).getRC4Header()); >+ } >+ > if (record instanceof EOFRecord) { > bofDepth--; > if (bofDepth < 1) { >Index: src/java/org/apache/poi/hssf/record/FilePassRecord.java >=================================================================== >--- src/java/org/apache/poi/hssf/record/FilePassRecord.java (revision 801584) >+++ src/java/org/apache/poi/hssf/record/FilePassRecord.java (working copy) >@@ -33,49 +33,86 @@ > public final class FilePassRecord > extends StandardRecord > { >- public final static short sid = 0x2F; >- private int field_1_encryptedpassword; >+ public static final short sid = 0x2F; >+ private int wEncryptionType; > >+ private static final int ENCRYPTION_XOR = 0; >+ private static final int ENCRYPTION_OTHER = 1; >+ >+ private static final int ENCRYPTION_OTHER_RC4 = 1; >+ private static final int ENCRYPTION_OTHER_CAPI_2 = 2; >+ private static final int ENCRYPTION_OTHER_CAPI_3 = 3; >+ >+ private RC4Header header; >+ > public FilePassRecord() > { > } > > public FilePassRecord(RecordInputStream in) > { >- field_1_encryptedpassword = in.readInt(); >+ wEncryptionType = in.readShort(); >+ >+ switch (wEncryptionType) { >+ case ENCRYPTION_XOR: >+ throw new RecordFormatException("HSSF does not currently support XOR obfuscation"); >+ case ENCRYPTION_OTHER: >+ int encryptionInfo = in.readShort(); >+ >+ switch (encryptionInfo) { >+ case ENCRYPTION_OTHER_RC4: >+ header = new RC4Header(in); >+ >+ return; >+ case ENCRYPTION_OTHER_CAPI_2: >+ case ENCRYPTION_OTHER_CAPI_3: >+ throw new RecordFormatException("HSSF does not currently support CryptoAPI encryption"); >+ default: >+ throw new RecordFormatException("Unknown encryption info "+wEncryptionType); >+ } >+ default: >+ throw new RecordFormatException("Unknown encryption type "+wEncryptionType); >+ } > > //Whilst i have read in the password, HSSF currently has no plans to support/decrypt the remainder > //of this workbook >- throw new RecordFormatException("HSSF does not currently support encrypted workbooks"); >+// throw new RecordFormatException("HSSF does not currently support encrypted workbooks"); > } > >- public String toString() >- { >- StringBuffer buffer = new StringBuffer(); >+ @Override >+ public String toString() { >+ StringBuilder buffer = new StringBuilder(); > > buffer.append("[FILEPASS]\n"); >- buffer.append(" .password = ").append(field_1_encryptedpassword) >- .append("\n"); >+ buffer.append(" .type = ").append(wEncryptionType) >+ .append('\n'); > buffer.append("[/FILEPASS]\n"); > return buffer.toString(); > } > >+ @Override > public void serialize(LittleEndianOutput out) { >- out.writeInt(( short ) field_1_encryptedpassword); > } > >+ @Override > protected int getDataSize() { > return 4; > } > >+ @Override > public short getSid() > { > return sid; > } > >+ @Override > public Object clone() { > FilePassRecord rec = new FilePassRecord(); >- rec.field_1_encryptedpassword = field_1_encryptedpassword; >+ rec.wEncryptionType = wEncryptionType; > return rec; > } >+ >+ public RC4Header getRC4Header() { >+ return header; >+ } > } >Index: src/testcases/org/apache/poi/hssf/extractor/TestExcelExtractor.java >=================================================================== >--- src/testcases/org/apache/poi/hssf/extractor/TestExcelExtractor.java (revision 801584) >+++ src/testcases/org/apache/poi/hssf/extractor/TestExcelExtractor.java (working copy) >@@ -24,6 +24,7 @@ > import junit.framework.TestCase; > > import org.apache.poi.hssf.HSSFTestDataSamples; >+import org.apache.poi.hssf.record.RC4Header; > import org.apache.poi.hssf.usermodel.HSSFWorkbook; > import org.apache.poi.poifs.filesystem.DirectoryNode; > import org.apache.poi.poifs.filesystem.POIFSFileSystem; >@@ -289,4 +290,13 @@ > assertTrue("Unable to find expected word in text\n" + text, text.indexOf("test phrase") >= 0); > } > } >+ >+ public void testPassword() { >+ RC4Header.setPassword("password"); >+ ExcelExtractor extractor = createExtractor("password.xls"); >+ String text = extractor.getText(); >+ RC4Header.setPassword(null); >+ >+ assertTrue(text.contains("ZIP")); >+ } > }
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 47652
: 24105 |
24106
|
24107
|
24108
|
24136