From 9f98f07f23346fac51044085a41626b5bc399f31 Mon Sep 17 00:00:00 2001 From: ElenaSubbotina Date: Sun, 25 Jun 2017 14:20:14 +0300 Subject: [PATCH] Decryptors ... small refactoring --- .../DocDocxConverter/WordDocument.cpp | 20 +---- .../source/XlsFormat/Binary/CFRecord.cpp | 4 +- .../XlsFormat/Crypt/BiffDecoder_RCF.cpp | 72 +++++++++--------- .../source/XlsFormat/Crypt/BiffDecoder_RCF.h | 31 ++++---- .../source/XlsFormat/Crypt/BinaryCodec_RCF.h | 2 +- .../source/XlsFormat/Crypt/Crypt.h | 4 +- .../source/XlsFormat/Crypt/Decryptor.cpp | 16 ++-- .../source/XlsFormat/Crypt/Decryptor.h | 7 +- .../source/XlsFormat/Crypt/RC4Crypt.cpp | 34 +++++---- .../source/XlsFormat/Crypt/RC4Crypt.h | 6 +- .../XlsFormat/Logic/Biff_records/FilePass.cpp | 2 +- .../XlsFormat/Logic/Biff_records/StyleExt.cpp | 1 + .../Biff_structures/RC4EncryptionHeader.cpp | 49 ++++++------ .../Biff_structures/RC4EncryptionHeader.h | 2 +- .../Logic/Biff_structures/XFProp.cpp | 5 +- .../source/XlsXlsxConverter/XlsConverter.cpp | 6 +- .../source/win32/XlsFormat.vcproj | 4 - OfficeCryptReader/source/CryptTransform.cpp | 76 +++++++++++++++++-- OfficeCryptReader/source/CryptTransform.h | 8 +- OfficeCryptReader/source/ECMACryptFile.cpp | 42 +++++----- 20 files changed, 225 insertions(+), 166 deletions(-) diff --git a/ASCOfficeDocFile/DocDocxConverter/WordDocument.cpp b/ASCOfficeDocFile/DocDocxConverter/WordDocument.cpp index dda10487de..7c45f1e7ef 100644 --- a/ASCOfficeDocFile/DocDocxConverter/WordDocument.cpp +++ b/ASCOfficeDocFile/DocDocxConverter/WordDocument.cpp @@ -139,7 +139,7 @@ namespace DocFileFormat if (encryptionHeader->bStandard) { - CRYPT::RC4Decryptor Decryptor(encryptionHeader->crypt_data_rc4, m_sPassword, 1); + CRYPT::RC4Decryptor Decryptor(encryptionHeader->crypt_data_rc4, m_sPassword); if (Decryptor.IsVerify() == false) { @@ -153,24 +153,6 @@ namespace DocFileFormat } else { - //POLE::Stream * pStream = NULL; - //if (m_pStorage->GetStream ("EncryptedSummaryInformation", &pStream)) - //{ - // VirtualStreamReader tStream( pStream, 0, FIB->m_bOlderVersion); - - // _UINT32 StreamDescriptorArrayOffset = tStream.ReadUInt32(); - // _UINT32 StreamDescriptorArraySize = tStream.ReadUInt32(); - - // for (int i = 0; i < StreamDescriptorArraySize; i++) - // { - // } - // _UINT32 EncryptedStreamDescriptorCount = tStream.ReadUInt32(); - - // for (int i = 0; i < EncryptedStreamDescriptorCount; i++) - // { - // } - // RELEASEOBJECT(pStream); - //} CRYPT::ECMADecryptor Decryptor; Decryptor.SetCryptData(encryptionHeader->crypt_data_aes); diff --git a/ASCOfficeXlsFile2/source/XlsFormat/Binary/CFRecord.cpp b/ASCOfficeXlsFile2/source/XlsFormat/Binary/CFRecord.cpp index 7e498f8cd8..2d4be75399 100644 --- a/ASCOfficeXlsFile2/source/XlsFormat/Binary/CFRecord.cpp +++ b/ASCOfficeXlsFile2/source/XlsFormat/Binary/CFRecord.cpp @@ -70,10 +70,10 @@ CFRecord::CFRecord(CFStreamPtr stream, GlobalWorkbookInfoPtr global_info) case rt_RRDHead: break; case rt_BoundSheet8: - global_info->decryptor->Decrypt(data_ + sizeof(unsigned int), size_ - sizeof(unsigned int), rec_data_pos + sizeof(unsigned int)); + global_info->decryptor->Decrypt(data_ + sizeof(unsigned int), size_ - sizeof(unsigned int), rec_data_pos + sizeof(unsigned int), 1024); break; default: - global_info->decryptor->Decrypt(data_, size_, rec_data_pos); + global_info->decryptor->Decrypt(data_, size_, rec_data_pos, 1024); break; } } diff --git a/ASCOfficeXlsFile2/source/XlsFormat/Crypt/BiffDecoder_RCF.cpp b/ASCOfficeXlsFile2/source/XlsFormat/Crypt/BiffDecoder_RCF.cpp index fe7c5da6fb..57c47cafcd 100644 --- a/ASCOfficeXlsFile2/source/XlsFormat/Crypt/BiffDecoder_RCF.cpp +++ b/ASCOfficeXlsFile2/source/XlsFormat/Crypt/BiffDecoder_RCF.cpp @@ -34,10 +34,8 @@ namespace CRYPT { - -BiffDecoderBase::BiffDecoderBase(int BLOCKSIZE) : mbValid(false) +BiffDecoderBase::BiffDecoderBase() : mbValid(false) { - RCF_BLOCKSIZE = BLOCKSIZE; } @@ -51,34 +49,29 @@ bool BiffDecoderBase::verifyPassword(const std::wstring& rPassword) mbValid = implVerify(rPassword); return mbValid; } - - -void BiffDecoderBase::decode(unsigned char* pnDestData, const unsigned char* pnSrcData, const long nStreamPos, const unsigned short nBytes) +void BiffDecoderBase::decode(unsigned char* pnDestData, const unsigned char* pnSrcData, const unsigned short nBytes, const long block_index) { if(pnDestData && pnSrcData && (nBytes> 0)) { if(mbValid) - implDecode(pnDestData, pnSrcData, nStreamPos, nBytes); + implDecode(pnDestData, pnSrcData, nBytes, block_index); + else + memcpy(pnDestData, pnSrcData, nBytes); + }} + +void BiffDecoderBase::decode(unsigned char* pnDestData, const unsigned char* pnSrcData, const unsigned short nBytes, const long nStreamPos, const unsigned short block_size) +{ + if(pnDestData && pnSrcData && (nBytes> 0)) + { + if(mbValid) + implDecode(pnDestData, pnSrcData, nBytes, nStreamPos, block_size); else memcpy(pnDestData, pnSrcData, nBytes); } } -/** Returns the block index of the passed stream position for RCF decryption. */ -int BiffDecoderBase::lclGetRcfBlock(long nStreamPos) -{ - return static_cast(nStreamPos / RCF_BLOCKSIZE); -} - -/** Returns the offset of the passed stream position in a block for RCF decryption. */ -int BiffDecoderBase::lclGetRcfOffset(long nStreamPos) -{ - return static_cast(nStreamPos % RCF_BLOCKSIZE); -} - - -BiffDecoder_RCF::BiffDecoder_RCF(unsigned char pnSalt[16], unsigned char pnVerifier[16], unsigned char pnVerifierHash[16], int BlockSize) -: BiffDecoderBase(BlockSize), +BiffDecoder_RCF::BiffDecoder_RCF(unsigned char pnSalt[16], unsigned char pnVerifier[16], unsigned char pnVerifierHash[16]) +: maPassword(16, 0), maSalt(pnSalt, pnSalt + 16), maVerifier(pnVerifier, pnVerifier + 16), @@ -107,28 +100,37 @@ bool BiffDecoder_RCF::implVerify(const std::wstring& rPassword) } return false; } - -void BiffDecoder_RCF::implDecode(unsigned char* pnDestData, const unsigned char* pnSrcData, const long nStreamPos, const unsigned short nBytes) +void BiffDecoder_RCF::implDecode(unsigned char* pnDestData, const unsigned char* pnSrcData, const unsigned short nBytes, const long block_index) { - unsigned char* pnCurrDest = pnDestData; - const unsigned char* pnCurrSrc = pnSrcData; - long nCurrPos = nStreamPos; - unsigned short nBytesLeft = nBytes; - while(nBytesLeft> 0) + maCodec.startBlock(block_index); + maCodec.decode(pnDestData, pnSrcData, static_cast(nBytes)); +} +void BiffDecoder_RCF::implDecode(unsigned char* pnDestData, const unsigned char* pnSrcData, const unsigned short nBytes, const long nStreamPos, const unsigned short block_size) +{ + unsigned char* pnCurrDest = pnDestData; + const unsigned char* pnCurrSrc = pnSrcData; + long nCurrPos = nStreamPos; + unsigned short nBytesLeft = nBytes; + + while(nBytesLeft > 0) { // initialize codec for current stream position - maCodec.startBlock(lclGetRcfBlock(nCurrPos)); - maCodec.skip(lclGetRcfOffset(nCurrPos)); + maCodec.startBlock (nCurrPos / block_size); + + const long offset = nCurrPos % block_size; + maCodec.skip (offset); // decode the block - unsigned short nBlockLeft = static_cast(get_BLOCKSIZE() - lclGetRcfOffset(nCurrPos)); + unsigned short nBlockLeft = static_cast(block_size - offset); unsigned short nDecBytes = nBytesLeft < nBlockLeft ? nBytesLeft : nBlockLeft; + maCodec.decode(pnCurrDest, pnCurrSrc, static_cast(nDecBytes)); // prepare for next block - pnCurrDest += nDecBytes; - pnCurrSrc += nDecBytes; - nCurrPos += nDecBytes; + pnCurrDest += nDecBytes; + pnCurrSrc += nDecBytes; + nCurrPos += nDecBytes; + nBytesLeft = nBytesLeft - nDecBytes; } } diff --git a/ASCOfficeXlsFile2/source/XlsFormat/Crypt/BiffDecoder_RCF.h b/ASCOfficeXlsFile2/source/XlsFormat/Crypt/BiffDecoder_RCF.h index 142bb0de1c..e43420daf1 100644 --- a/ASCOfficeXlsFile2/source/XlsFormat/Crypt/BiffDecoder_RCF.h +++ b/ASCOfficeXlsFile2/source/XlsFormat/Crypt/BiffDecoder_RCF.h @@ -44,12 +44,10 @@ namespace CRYPT class BiffDecoderBase { public: - explicit BiffDecoderBase(int BLOCKSIZE); + explicit BiffDecoderBase(); virtual ~BiffDecoderBase(); - int get_BLOCKSIZE(){return RCF_BLOCKSIZE;} - - /** Implementation of the ::comphelper::IDocPasswordVerifier interface, + /** Implementation of the ::comphelper::IDocPasswordVerifier interface, calls the new virtual function implVerify(). */ virtual bool verifyPassword( const std::wstring& rPassword ); @@ -57,21 +55,18 @@ public: inline bool isValid() const { return mbValid; } /** Decodes nBytes unsigned chars and writes encrypted data into the buffer pnDestData. */ - void decode(unsigned char* pnDestData, const unsigned char* pnSrcData, const long nStreamPos, const unsigned short nBytes); - - int lclGetRcfBlock(long nStreamPos); - int lclGetRcfOffset(long nStreamPos); + virtual void decode(unsigned char* pnDestData, const unsigned char* pnSrcData, const unsigned short nBytes, const long nStreamPos, const unsigned short block_size); + virtual void decode(unsigned char* pnDestData, const unsigned char* pnSrcData, const unsigned short nBytes, const long block_index); private: - int RCF_BLOCKSIZE; - /** Derived classes implement password verification and initialization of the decoder. */ virtual bool implVerify(const std::wstring& rPassword) = 0; /** Implementation of decryption of a memory block. */ - virtual void implDecode(unsigned char* pnDestData, const unsigned char* pnSrcData, const long nStreamPos, const unsigned short nBytes) = 0; + virtual void implDecode(unsigned char* pnDestData, const unsigned char* pnSrcData, const unsigned short nBytes, const long nStreamPos, const unsigned short block_size) = 0; + virtual void implDecode(unsigned char* pnDestData, const unsigned char* pnSrcData, const unsigned short nBytes, const long block_index) = 0; private: bool mbValid; /// True = decoder is correctly initialized. @@ -83,7 +78,7 @@ typedef ::boost::shared_ptr BiffDecoderRef; class BiffDecoder_RCF : public BiffDecoderBase { public: - explicit BiffDecoder_RCF(unsigned char pnSalt[ 16 ], unsigned char pnVerifier[ 16 ], unsigned char pnVerifierHash[ 16 ], int BlockSize); + explicit BiffDecoder_RCF(unsigned char pnSalt[ 16 ], unsigned char pnVerifier[ 16 ], unsigned char pnVerifierHash[ 16 ]); private: @@ -91,14 +86,14 @@ private: virtual bool implVerify(const std::wstring& rPassword); /** Implementation of decryption of a memory block. */ - virtual void implDecode(unsigned char* pnDestData, const unsigned char* pnSrcData, const long nStreamPos, const unsigned short nBytes); + virtual void implDecode(unsigned char* pnDestData, const unsigned char* pnSrcData, const unsigned short nBytes, const long nStreamPos, const unsigned short block_size); + virtual void implDecode(unsigned char* pnDestData, const unsigned char* pnSrcData, const unsigned short nBytes, const long block_index); -private: - BinaryCodec_RCF maCodec; /// Cipher algorithm implementation. + BinaryCodec_RCF maCodec; /// Cipher algorithm implementation. std::vector maPassword; - std::vector maSalt; - std::vector maVerifier; - std::vector maVerifierHash; + std::vector maSalt; + std::vector maVerifier; + std::vector maVerifierHash; }; diff --git a/ASCOfficeXlsFile2/source/XlsFormat/Crypt/BinaryCodec_RCF.h b/ASCOfficeXlsFile2/source/XlsFormat/Crypt/BinaryCodec_RCF.h index e63020dfc5..768e3bb5b5 100644 --- a/ASCOfficeXlsFile2/source/XlsFormat/Crypt/BinaryCodec_RCF.h +++ b/ASCOfficeXlsFile2/source/XlsFormat/Crypt/BinaryCodec_RCF.h @@ -143,7 +143,7 @@ public: private: CipherARCFOUR mhCipher; DigestMD5 mhDigest; - unsigned char mpnDigestValue[DigestMD5::RTL_DIGEST_LENGTH_MD5]; + unsigned char mpnDigestValue[DigestMD5::RTL_DIGEST_LENGTH_MD5]; }; diff --git a/ASCOfficeXlsFile2/source/XlsFormat/Crypt/Crypt.h b/ASCOfficeXlsFile2/source/XlsFormat/Crypt/Crypt.h index e454459fc1..66dc2074c1 100644 --- a/ASCOfficeXlsFile2/source/XlsFormat/Crypt/Crypt.h +++ b/ASCOfficeXlsFile2/source/XlsFormat/Crypt/Crypt.h @@ -68,8 +68,8 @@ namespace CRYPT { public: - virtual void Encrypt(char* data, const size_t size) = 0; - virtual void Decrypt(char* data, const size_t size, const unsigned long stream_pos) = 0; + virtual void Decrypt(char* data, const size_t size, const unsigned long stream_pos, const size_t block_size) = 0; + virtual void Decrypt(char* data, const size_t size, const unsigned long block_index) = 0; typedef enum { diff --git a/ASCOfficeXlsFile2/source/XlsFormat/Crypt/Decryptor.cpp b/ASCOfficeXlsFile2/source/XlsFormat/Crypt/Decryptor.cpp index 432621f844..e40a03cf9d 100644 --- a/ASCOfficeXlsFile2/source/XlsFormat/Crypt/Decryptor.cpp +++ b/ASCOfficeXlsFile2/source/XlsFormat/Crypt/Decryptor.cpp @@ -37,18 +37,20 @@ namespace CRYPT { - RC4Decryptor::RC4Decryptor(_rc4CryptData & header, std::wstring _password, int _type) : - crypt(new RC4Crypt(header, _password, _type)) + RC4Decryptor::RC4Decryptor(_rc4CryptData & header, std::wstring _password) : + crypt(new RC4Crypt(header, _password)) { crypt_data = header; - type = _type; } - void RC4Decryptor::Decrypt(char* data, const size_t size, const unsigned long stream_pos) + void RC4Decryptor::Decrypt(char* data, const size_t size, const unsigned long stream_pos, const size_t block_size) { - crypt->Decrypt(data, size, stream_pos); + crypt->Decrypt(data, size, stream_pos, block_size); + } + void RC4Decryptor::Decrypt(char* data, const size_t size, const unsigned long block_index) + { + crypt->Decrypt(data, size, block_index); } - bool RC4Decryptor::IsVerify() { return crypt->IsVerify(); @@ -57,7 +59,7 @@ namespace CRYPT bool RC4Decryptor::SetPassword(std::wstring password) { crypt.reset(); - crypt = CryptPtr(new RC4Crypt(crypt_data, password, type)); + crypt = CryptPtr(new RC4Crypt(crypt_data, password)); if (crypt) return crypt->IsVerify(); else return false; diff --git a/ASCOfficeXlsFile2/source/XlsFormat/Crypt/Decryptor.h b/ASCOfficeXlsFile2/source/XlsFormat/Crypt/Decryptor.h index 28d9253c56..7fbdfcd348 100644 --- a/ASCOfficeXlsFile2/source/XlsFormat/Crypt/Decryptor.h +++ b/ASCOfficeXlsFile2/source/XlsFormat/Crypt/Decryptor.h @@ -40,15 +40,16 @@ namespace CRYPT class RC4Decryptor : public Decryptor { public: - RC4Decryptor(_rc4CryptData & header, std::wstring password, int type); + RC4Decryptor(_rc4CryptData & header, std::wstring password); - virtual void Decrypt(char* data, const size_t size, const unsigned long stream_pos); + virtual void Decrypt(char* data, const size_t size, const unsigned long stream_pos, const size_t block_size); + virtual void Decrypt(char* data, const size_t size, const unsigned long block_index); + virtual bool SetPassword(std::wstring password); virtual bool IsVerify(); private: - int type; CryptPtr crypt; _rc4CryptData crypt_data; }; diff --git a/ASCOfficeXlsFile2/source/XlsFormat/Crypt/RC4Crypt.cpp b/ASCOfficeXlsFile2/source/XlsFormat/Crypt/RC4Crypt.cpp index 185fcd36e4..ecb431dc5d 100644 --- a/ASCOfficeXlsFile2/source/XlsFormat/Crypt/RC4Crypt.cpp +++ b/ASCOfficeXlsFile2/source/XlsFormat/Crypt/RC4Crypt.cpp @@ -38,7 +38,7 @@ namespace CRYPT { -RC4Crypt::RC4Crypt(CRYPT::_rc4CryptData & data, std::wstring password, int type) +RC4Crypt::RC4Crypt(CRYPT::_rc4CryptData & data, std::wstring password) { m_VerifyPassword = false; @@ -46,18 +46,11 @@ RC4Crypt::RC4Crypt(CRYPT::_rc4CryptData & data, std::wstring password, int type) CopyDWORDs2Bytes(data.EncryptedVerifier.b1 , data.EncryptedVerifier.b2, data.EncryptedVerifier.b3, data.EncryptedVerifier.b4, pnVerifier); CopyDWORDs2Bytes(data.EncryptedVerifierHash.b1, data.EncryptedVerifierHash.b2, data.EncryptedVerifierHash.b3, data.EncryptedVerifierHash.b4, pnVerifierHash); - int BlockSize = 1024; - if (type == 1) BlockSize = 512; - - mxDecoder.reset(new BiffDecoder_RCF(pnSalt, pnVerifier, pnVerifierHash, BlockSize)); + mxDecoder.reset(new BiffDecoder_RCF(pnSalt, pnVerifier, pnVerifierHash)); m_VerifyPassword = mxDecoder->verifyPassword(password); } -void RC4Crypt::Encrypt(char* data, const size_t size) -{ - -} bool RC4Crypt::IsVerify() { @@ -87,18 +80,33 @@ void RC4Crypt::CopyDWORDs2Bytes(const unsigned int b1, const unsigned int b2, co byte_array[15] = static_cast((b4 & 0xff000000) >> 24); } -void RC4Crypt::Decrypt(char* data, const size_t size, const unsigned long stream_pos) +void RC4Crypt::Decrypt(char* data, const size_t size, const unsigned long block_index) { - static unsigned char quick_buf[256]; if(size <= 256) { - mxDecoder->decode( quick_buf, reinterpret_cast(data), stream_pos, size ); + static unsigned char quick_buf[256]; + mxDecoder->decode( quick_buf, reinterpret_cast(data), size, block_index ); memcpy(data, quick_buf, size); } else { boost::scoped_array out_data(new unsigned char[size]); - mxDecoder->decode( out_data.get(), reinterpret_cast(data), stream_pos, size ); + mxDecoder->decode( out_data.get(), reinterpret_cast(data), size, block_index ); + memcpy(data, out_data.get(), size); + } +} +void RC4Crypt::Decrypt(char* data, const size_t size, const unsigned long stream_pos, const size_t block_size) +{ + if(size <= 256) + { + static unsigned char quick_buf[256]; + mxDecoder->decode( quick_buf, reinterpret_cast(data), size, stream_pos, block_size ); + memcpy(data, quick_buf, size); + } + else + { + boost::scoped_array out_data(new unsigned char[size]); + mxDecoder->decode( out_data.get(), reinterpret_cast(data), size, stream_pos, block_size ); memcpy(data, out_data.get(), size); } } diff --git a/ASCOfficeXlsFile2/source/XlsFormat/Crypt/RC4Crypt.h b/ASCOfficeXlsFile2/source/XlsFormat/Crypt/RC4Crypt.h index e2b7d6cab7..b366a9261d 100644 --- a/ASCOfficeXlsFile2/source/XlsFormat/Crypt/RC4Crypt.h +++ b/ASCOfficeXlsFile2/source/XlsFormat/Crypt/RC4Crypt.h @@ -41,10 +41,10 @@ namespace CRYPT class RC4Crypt : public Crypt { public: - RC4Crypt(CRYPT::_rc4CryptData & data, std::wstring password, int type); + RC4Crypt(CRYPT::_rc4CryptData & data, std::wstring password); - virtual void Encrypt(char* data, const size_t size); - virtual void Decrypt(char* data, const size_t size, const unsigned long stream_pos); + virtual void Decrypt(char* data, const size_t size, const unsigned long stream_pos, const size_t block_size); + virtual void Decrypt(char* data, const size_t size, const unsigned long block_index); virtual bool IsVerify(); diff --git a/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_records/FilePass.cpp b/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_records/FilePass.cpp index f4fca0fd6b..9863c6ae13 100644 --- a/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_records/FilePass.cpp +++ b/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_records/FilePass.cpp @@ -79,7 +79,7 @@ void FilePass::readFields(CFRecord& record) if (cryptHeaderPtr->bStandard) { record.getGlobalWorkbookInfo()->decryptor = - CRYPT::DecryptorPtr(new CRYPT::RC4Decryptor(cryptHeaderPtr->crypt_data_rc4, record.getGlobalWorkbookInfo()->password, 2)); + CRYPT::DecryptorPtr(new CRYPT::RC4Decryptor(cryptHeaderPtr->crypt_data_rc4, record.getGlobalWorkbookInfo()->password)); } else { diff --git a/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_records/StyleExt.cpp b/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_records/StyleExt.cpp index 22167ea57b..12091e0b89 100644 --- a/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_records/StyleExt.cpp +++ b/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_records/StyleExt.cpp @@ -61,6 +61,7 @@ void StyleExt::readFields(CFRecord& record) fHidden = GETBIT(flags, 1); fCustom = GETBIT(flags, 2); + stName.setSize(0xff); //max size record >> iCategory>> builtInData >> stName >> xfProps; } diff --git a/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_structures/RC4EncryptionHeader.cpp b/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_structures/RC4EncryptionHeader.cpp index c9f3ccc7c5..8333230ca7 100644 --- a/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_structures/RC4EncryptionHeader.cpp +++ b/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_structures/RC4EncryptionHeader.cpp @@ -125,33 +125,34 @@ void RC4EncryptionHeader::load(XLS::CFRecord& record) pos = record.getRdPtr(); //------------------------------------------------------------------------------------------ - crypt_data_aes.hashAlgorithm = CRYPT_METHOD::SHA1; //by AlgIDHash -> 0x0000(reserved ??) || 0x8004(sha1) - crypt_data_aes.spinCount = 50000; + switch(AlgIDHash) + { + case 0x8003: crypt_data_aes.hashAlgorithm = CRYPT_METHOD::MD5; break; + case 0x0000: + case 0x8004: crypt_data_aes.hashAlgorithm = CRYPT_METHOD::SHA1; break; + } + crypt_data_aes.spinCount = 0; switch(AlgID) { - case 0x6801: - crypt_data_aes.cipherAlgorithm = CRYPT_METHOD::RC4; - crypt_data_aes.keySize = KeySize / 8; - break; - case 0x660E: - crypt_data_aes.cipherAlgorithm = CRYPT_METHOD::AES_ECB; - crypt_data_aes.keySize = 128 /8; - break; - case 0x660F: - crypt_data_aes.cipherAlgorithm = CRYPT_METHOD::AES_ECB; - crypt_data_aes.keySize = 192 /8; - break; - case 0x6610: - crypt_data_aes.cipherAlgorithm = CRYPT_METHOD::AES_ECB; - crypt_data_aes.keySize = 256 /8; - break; - } - - switch(ProviderType) - { - case 0x0001: crypt_data_aes.cipherAlgorithm = CRYPT_METHOD::RC4; break; - case 0x0018: crypt_data_aes.cipherAlgorithm = CRYPT_METHOD::AES_ECB; break; + case 0x6801: + crypt_data_aes.cipherAlgorithm = CRYPT_METHOD::RC4; + crypt_data_aes.keySize = KeySize / 8; + + if (crypt_data_aes.keySize == 0)crypt_data_aes.keySize = 5; // 40 bit + break; + case 0x660E: + crypt_data_aes.cipherAlgorithm = CRYPT_METHOD::AES_ECB; + crypt_data_aes.keySize = 128 /8; + break; + case 0x660F: + crypt_data_aes.cipherAlgorithm = CRYPT_METHOD::AES_ECB; + crypt_data_aes.keySize = 192 /8; + break; + case 0x6610: + crypt_data_aes.cipherAlgorithm = CRYPT_METHOD::AES_ECB; + crypt_data_aes.keySize = 256 /8; + break; } } } diff --git a/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_structures/RC4EncryptionHeader.h b/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_structures/RC4EncryptionHeader.h index 110280da3c..672241968b 100644 --- a/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_structures/RC4EncryptionHeader.h +++ b/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_structures/RC4EncryptionHeader.h @@ -33,7 +33,7 @@ #include "BiffStructure.h" #include -#include "../../Crypt/Crypt.h" +#include "../../Crypt/RC4Crypt.h" namespace CRYPTO { diff --git a/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_structures/XFProp.cpp b/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_structures/XFProp.cpp index a153561a0d..d8e302afdb 100644 --- a/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_structures/XFProp.cpp +++ b/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_structures/XFProp.cpp @@ -134,7 +134,10 @@ void XFProp::load(CFRecord& record) // EXCEPT::RT::WrongBiffRecord("Unsupported type of XFProp.", record.getTypeString()); break; } - record >> *xfPropDataBlob; + if (xfPropDataBlob) + { + record >> *xfPropDataBlob; + } } static void serialize_color_prop(std::wostream & stream, const std::wstring & name, BiffStructurePtr & val) { diff --git a/ASCOfficeXlsFile2/source/XlsXlsxConverter/XlsConverter.cpp b/ASCOfficeXlsFile2/source/XlsXlsxConverter/XlsConverter.cpp index 70f0b9eeda..cb06a2079e 100644 --- a/ASCOfficeXlsFile2/source/XlsXlsxConverter/XlsConverter.cpp +++ b/ASCOfficeXlsFile2/source/XlsXlsxConverter/XlsConverter.cpp @@ -530,7 +530,11 @@ void XlsConverter::convert(XLS::FORMATTING* formating) CP_XML_NODE(L"styleSheet") { CP_XML_ATTR(L"xmlns", L"http://schemas.openxmlformats.org/spreadsheetml/2006/main"); - + CP_XML_ATTR(L"xmlns:mc", L"http://schemas.openxmlformats.org/markup-compatibility/2006"); + CP_XML_ATTR(L"mc:Ignorable", L"x14ac x16r2"); + CP_XML_ATTR(L"xmlns:x14ac", L"http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac"); + CP_XML_ATTR(L"xmlns:x16r2", L"http://schemas.microsoft.com/office/spreadsheetml/2015/02/main"); + formating->serialize1(CP_XML_STREAM()); //важен порядок в styles CP_XML_NODE(L"fills") diff --git a/ASCOfficeXlsFile2/source/win32/XlsFormat.vcproj b/ASCOfficeXlsFile2/source/win32/XlsFormat.vcproj index 5545408c7d..d945363e46 100644 --- a/ASCOfficeXlsFile2/source/win32/XlsFormat.vcproj +++ b/ASCOfficeXlsFile2/source/win32/XlsFormat.vcproj @@ -6202,10 +6202,6 @@ RelativePath="..\XlsFormat\Crypt\BinaryCodec_RCF.h" > - - diff --git a/OfficeCryptReader/source/CryptTransform.cpp b/OfficeCryptReader/source/CryptTransform.cpp index 4df6089e8c..19f0fdee58 100644 --- a/OfficeCryptReader/source/CryptTransform.cpp +++ b/OfficeCryptReader/source/CryptTransform.cpp @@ -513,16 +513,75 @@ void ECMADecryptor::SetCryptData(_ecmaCryptData & data) } void ECMADecryptor::Decrypt(char* data , const size_t size, const unsigned long start_iv_block) { - if (bVerify) + if (!bVerify) return; + + unsigned char* data_out = NULL; + Decrypt((unsigned char*)data, size, data_out, start_iv_block); + + if (data_out) { - unsigned char* data_out = NULL; - Decrypt((unsigned char*)data, size, data_out, start_iv_block); - - if (data_out) + memcpy(data, data_out, size); + delete []data_out; + } +} +void ECMADecryptor::Decrypt(char* data , const size_t size, const unsigned long stream_pos, const size_t block_size) +{ + if (!bVerify) return; +//rc4 only + if (cryptData.cipherAlgorithm != CRYPT_METHOD::RC4) return; + + unsigned char* data_out = new unsigned char[size]; + + unsigned char* pnCurrDest = data_out; + const unsigned char* pnCurrSrc = (unsigned char* )data; + long nCurrPos = stream_pos; + unsigned short nBytesLeft = size; + + while(nBytesLeft > 0) + { + // initialize codec for current stream position + + int block_index = (nCurrPos / block_size); { - memcpy(data, data_out, size); - delete []data_out; + _buf pPassword (password); + _buf pSalt (cryptData.saltValue); + + _buf hashKey = GenerateHashKey(pSalt, pPassword, cryptData.hashSize, cryptData.spinCount, cryptData.hashAlgorithm, block_index); + CorrectHashSize(hashKey, cryptData.keySize, 0); + + if (cryptData.keySize == 5) CorrectHashSize(hashKey, 16, 0); //40-bit crypt key !!! + + rc4Decryption.SetKey(hashKey.ptr, hashKey.size); } + + const long offset = nCurrPos % block_size; + {//skip + unsigned char pnDummy[ 1024 ]; + + size_t nBytesLeft = offset; + bool bResult = true; + while(bResult && (nBytesLeft > 0)) + { + size_t nBlockLen = nBytesLeft < sizeof(pnDummy) ? nBytesLeft : sizeof(pnDummy); + rc4Decryption.ProcessData(pnDummy, pnDummy, nBlockLen); + nBytesLeft -= nBlockLen; + } + } + unsigned short nBlockLeft = static_cast(block_size - offset); + unsigned short nDecBytes = nBytesLeft < nBlockLeft ? nBytesLeft : nBlockLeft; + + rc4Decryption.ProcessData(pnCurrDest, pnCurrSrc, static_cast(nDecBytes)); + + pnCurrDest += nDecBytes; + pnCurrSrc += nDecBytes; + nCurrPos += nDecBytes; + + nBytesLeft = nBytesLeft - nDecBytes; + } + if (data_out) + { + memcpy(data, data_out, size); + delete []data_out; } } bool ECMADecryptor::CheckDataIntegrity(unsigned char* data, int size) @@ -564,7 +623,8 @@ bool ECMADecryptor::CheckDataIntegrity(unsigned char* data, int size) return (hmac == expected); } -void ECMADecryptor::Decrypt(unsigned char* data_inp, int size, unsigned char*& data_out, int start_iv_block) + +void ECMADecryptor::Decrypt(unsigned char* data_inp, int size, unsigned char*& data_out, unsigned long start_iv_block) { data_out = new unsigned char[size]; diff --git a/OfficeCryptReader/source/CryptTransform.h b/OfficeCryptReader/source/CryptTransform.h index 3bec55b81f..06791012a7 100644 --- a/OfficeCryptReader/source/CryptTransform.h +++ b/OfficeCryptReader/source/CryptTransform.h @@ -62,7 +62,8 @@ namespace CRYPT class Decryptor { public: - virtual void Decrypt(char* data, const size_t size, const unsigned long stream_pos) = 0; + virtual void Decrypt(char* data, const size_t size, const unsigned long stream_pos, const size_t block_size) = 0; + virtual void Decrypt(char* data, const size_t size, const unsigned long block_index) = 0; virtual bool SetPassword(std::wstring password) = 0; virtual bool IsVerify() = 0; @@ -128,9 +129,10 @@ public: ECMADecryptor(); virtual ~ECMADecryptor(); - void Decrypt (unsigned char* data, int size, unsigned char*& data_out, int start_iv_block = 0); + virtual void Decrypt (char* data, const size_t size, const unsigned long stream_pos, const size_t block_size); virtual void Decrypt (char* data, const size_t size, const unsigned long start_iv_block); + virtual bool SetPassword (std::wstring password); virtual bool IsVerify(); @@ -138,6 +140,8 @@ public: void SetCryptData(_ecmaCryptData &data); + void Decrypt (unsigned char* data, int size, unsigned char*& data_out, unsigned long start_iv_block); + private: std::wstring password; diff --git a/OfficeCryptReader/source/ECMACryptFile.cpp b/OfficeCryptReader/source/ECMACryptFile.cpp index f94b3324cd..17fb2092af 100644 --- a/OfficeCryptReader/source/ECMACryptFile.cpp +++ b/OfficeCryptReader/source/ECMACryptFile.cpp @@ -565,26 +565,26 @@ bool ECMACryptFile::EncryptOfficeFile(std::wstring file_name_inp, std::wstring f pStorage->close(); delete pStorage; - -//test back---------------------------------------------------------------------------------test back - ECMADecryptor decryptor; - - decryptor.SetCryptData(cryptData); - - if (decryptor.SetPassword(password)) - { - unsigned char* data_out2 = NULL; - decryptor.Decrypt(data_out, lengthData, data_out2); - - bool bDataIntegrity = decryptor.CheckDataIntegrity(data_out, lengthData); - - NSFile::CFileBinary test; - - test.CreateFileW(file_name_out + L"-back.oox"); - test.WriteFile(data_out2, lengthFileSize); - test.CloseFile(); - } -//test back---------------------------------------------------------------------------------test back +// +////test back---------------------------------------------------------------------------------test back +// ECMADecryptor decryptor; +// +// decryptor.SetCryptData(cryptData); +// +// if (decryptor.SetPassword(password)) +// { +// unsigned char* data_out2 = NULL; +// decryptor.Decrypt(data_out, lengthData, data_out2, 0); +// +// bool bDataIntegrity = decryptor.CheckDataIntegrity(data_out, lengthData); +// +// NSFile::CFileBinary test; +// +// test.CreateFileW(file_name_out + L"-back.oox"); +// test.WriteFile(data_out2, lengthFileSize); +// test.CloseFile(); +// } +////test back---------------------------------------------------------------------------------test back return true; } @@ -717,7 +717,7 @@ bool ECMACryptFile::DecryptOfficeFile(std::wstring file_name_inp, std::wstring f lengthData = *((_UINT64*)data); - decryptor.Decrypt(data + 8, readData, data_out);//todoo сделать покусочное чтение декриптование + decryptor.Decrypt(data + 8, readData, data_out, 0);//todoo сделать покусочное чтение декриптование if (data_out) {