From: Andreas Beeker Date: Wed, 28 Sep 2016 23:36:09 +0000 (+0000) Subject: Bug 59857 - Password protected files with "Microsoft Enhanced Cryptographic Provider... X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=d8767e1c70cf65eee5f57c77abd8257114c3fc3c;p=poi.git Bug 59857 - Password protected files with "Microsoft Enhanced Cryptographic Provider v1.0" git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1762726 13f79535-47bb-0310-9956-ffa450edef68 --- d8767e1c70cf65eee5f57c77abd8257114c3fc3c diff --cc src/java/org/apache/poi/hssf/record/FilePassRecord.java index 7c8ae948f9,acb5c8da46..99f37e535f --- a/src/java/org/apache/poi/hssf/record/FilePassRecord.java +++ b/src/java/org/apache/poi/hssf/record/FilePassRecord.java @@@ -199,60 -62,74 +62,74 @@@ public final class FilePassRecord exten } public FilePassRecord(RecordInputStream in) { - _encryptionType = in.readUShort(); - - switch (_encryptionType) { - case ENCRYPTION_XOR: - _keyData = new XorKeyData(); - break; - case ENCRYPTION_OTHER: - _keyData = new Rc4KeyData(); - break; - default: - throw new RecordFormatException("Unknown encryption type " + _encryptionType); - } - - _keyData.read(in); - } - - private static byte[] read(RecordInputStream in, int size) { - byte[] result = new byte[size]; - in.readFully(result); - return result; + encryptionType = in.readUShort(); + + EncryptionMode preferredMode; + switch (encryptionType) { + case ENCRYPTION_XOR: + preferredMode = EncryptionMode.xor; + break; + case ENCRYPTION_OTHER: + preferredMode = EncryptionMode.cryptoAPI; + break; + default: + throw new EncryptedDocumentException("invalid encryption type"); + } + + try { + encryptionInfo = new EncryptionInfo(in, preferredMode); + } catch (IOException e) { + throw new EncryptedDocumentException(e); + } } - public void serialize(LittleEndianOutput out) { - out.writeShort(_encryptionType); - assert(_keyData != null); - _keyData.serialize(out); - @Override ++ @SuppressWarnings("resource") ++ @Override + public void serialize(LittleEndianOutput out) { + out.writeShort(encryptionType); + + byte data[] = new byte[1024]; + LittleEndianByteArrayOutputStream bos = new LittleEndianByteArrayOutputStream(data, 0); + + switch (encryptionInfo.getEncryptionMode()) { + case xor: + ((XOREncryptionHeader)encryptionInfo.getHeader()).write(bos); + ((XOREncryptionVerifier)encryptionInfo.getVerifier()).write(bos); + break; + case binaryRC4: + out.writeShort(encryptionInfo.getVersionMajor()); + out.writeShort(encryptionInfo.getVersionMinor()); + ((BinaryRC4EncryptionHeader)encryptionInfo.getHeader()).write(bos); + ((BinaryRC4EncryptionVerifier)encryptionInfo.getVerifier()).write(bos); + break; + case cryptoAPI: + out.writeShort(encryptionInfo.getVersionMajor()); + out.writeShort(encryptionInfo.getVersionMinor()); + out.writeInt(encryptionInfo.getEncryptionFlags()); + ((CryptoAPIEncryptionHeader)encryptionInfo.getHeader()).write(bos); + ((CryptoAPIEncryptionVerifier)encryptionInfo.getVerifier()).write(bos); + break; + default: + throw new RuntimeException("not supported"); + } + + out.write(data, 0, bos.getWriteIndex()); } - protected int getDataSize() { - assert(_keyData != null); - return _keyData.getDataSize(); + @Override - @SuppressWarnings("resource") + protected int getDataSize() { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + LittleEndianOutputStream leos = new LittleEndianOutputStream(bos); + serialize(leos); + return bos.size(); } - public Rc4KeyData getRc4KeyData() { - return (_keyData instanceof Rc4KeyData) - ? (Rc4KeyData) _keyData - : null; - } - - public XorKeyData getXorKeyData() { - return (_keyData instanceof XorKeyData) - ? (XorKeyData) _keyData - : null; - } - - private Rc4KeyData checkRc4() { - Rc4KeyData rc4 = getRc4KeyData(); - if (rc4 == null) { - throw new RecordFormatException("file pass record doesn't contain a rc4 key."); - } - return rc4; + public EncryptionInfo getEncryptionInfo() { + return encryptionInfo; } - public short getSid() { + @Override + public short getSid() { return sid; } diff --cc src/java/org/apache/poi/hssf/record/RecordInputStream.java index f9212c7986,a3d84863e6..8fd0423933 --- a/src/java/org/apache/poi/hssf/record/RecordInputStream.java +++ b/src/java/org/apache/poi/hssf/record/RecordInputStream.java @@@ -23,8 -24,9 +24,8 @@@ 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.poifs.crypt.EncryptionInfo; + import org.apache.poi.util.Internal; import org.apache.poi.util.LittleEndianConsts; import org.apache.poi.util.LittleEndianInput; import org.apache.poi.util.LittleEndianInputStream; diff --cc src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java index f6456bffa3,b4339587b9..f6b8f1f292 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java @@@ -99,8 -105,11 +104,10 @@@ import org.apache.poi.ss.usermodel.Work import org.apache.poi.ss.util.WorkbookUtil; import org.apache.poi.util.Configurator; import org.apache.poi.util.HexDump; -import org.apache.poi.util.IOUtils; import org.apache.poi.util.Internal; import org.apache.poi.util.LittleEndian; + import org.apache.poi.util.LittleEndianByteArrayInputStream; + import org.apache.poi.util.LittleEndianByteArrayOutputStream; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; @@@ -119,7 -128,7 +126,6 @@@ public final class HSSFWorkbook extend * The maximum number of cell styles in a .xls workbook. * The 'official' limit is 4,000, but POI allows a slightly larger number. * This extra delta takes into account built-in styles that are automatically -- * created for new workbooks * * See http://office.microsoft.com/en-us/excel-help/excel-specifications-and-limits-HP005199291.aspx */