From 9aad3d1adb0ef924bd34358e8919c115f9677fce Mon Sep 17 00:00:00 2001 From: ElenaSubbotina Date: Wed, 3 Oct 2018 20:01:57 +0300 Subject: [PATCH] x2t - ooxml - not strong encryption --- ASCOfficeDocFile/Common/FormatUtils.h | 1 + .../DocDocxConverter/MemoryStream.h | 45 ++- .../Logic/Biff_unions/SUPBOOK_bu.cpp | 4 +- OfficeCryptReader/Test/Test.cpp | 23 +- OfficeCryptReader/source/CryptTransform.cpp | 367 +++++++++++++----- OfficeCryptReader/source/CryptTransform.h | 4 +- OfficeCryptReader/source/ECMACryptFile.cpp | 335 +++++++++++++--- X2tConverter/test/win32Test/X2tTest.vcproj | 16 +- 8 files changed, 606 insertions(+), 189 deletions(-) diff --git a/ASCOfficeDocFile/Common/FormatUtils.h b/ASCOfficeDocFile/Common/FormatUtils.h index e057bd369f..fc6644061d 100644 --- a/ASCOfficeDocFile/Common/FormatUtils.h +++ b/ASCOfficeDocFile/Common/FormatUtils.h @@ -54,6 +54,7 @@ #include "../../DesktopEditor/common/Types.h" #include "../../Common/DocxFormat/Source/Base/unicode_util.h" +#include "../../Common/DocxFormat/Source/Base/Types_32.h" #include "../../UnicodeConverter/UnicodeConverter.h" #include diff --git a/ASCOfficeDocFile/DocDocxConverter/MemoryStream.h b/ASCOfficeDocFile/DocDocxConverter/MemoryStream.h index 8874ed76fa..302490eea4 100644 --- a/ASCOfficeDocFile/DocDocxConverter/MemoryStream.h +++ b/ASCOfficeDocFile/DocDocxConverter/MemoryStream.h @@ -78,7 +78,14 @@ public: return rdUShort; } - + void WriteUInt16(unsigned short val) + { + if (m_Data) + { + ((unsigned short *)(m_Data + m_Position))[0] = val; + m_Position += sizeof(unsigned short); + } + } virtual short ReadInt16() { short rdShort = 0; @@ -104,7 +111,14 @@ public: return rdInt; } - + void WriteInt32(_INT32 val) + { + if (m_Data) + { + ((_INT32 *)(m_Data + m_Position))[0] = val; + m_Position += sizeof(_INT32); + } + } virtual unsigned int ReadUInt32() { int rdUInt = 0; @@ -117,7 +131,22 @@ public: return rdUInt; } - + void WriteByte(unsigned char val) + { + if (m_Data) + { + m_Data[m_Position] = val; + m_Position += 1; + } + } + void WriteUInt32(_UINT32 val) + { + if (m_Data) + { + ((_UINT32 *)(m_Data + m_Position))[0] = val; + m_Position += sizeof(_UINT32); + } + } virtual unsigned char ReadByte() { unsigned char rdByte = 0; @@ -159,6 +188,14 @@ public: return pBytes; } + void WriteBytes(unsigned char* pData, int size) + { + if (m_Data) + { + memcpy(m_Data + m_Position, pData, size); + m_Position += size; + } + } virtual unsigned long GetPosition() const { @@ -172,7 +209,7 @@ public: virtual int Seek (int offset, int origin = 0/*STREAM_SEEK_SET*/) { - if ( (m_Data != NULL) && (offset > 0) && ((unsigned int)offset < m_Size) ) + if ( (m_Data != NULL) && (offset >= 0) && ((unsigned int)offset < m_Size) ) return m_Position = offset; return 0; diff --git a/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_unions/SUPBOOK_bu.cpp b/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_unions/SUPBOOK_bu.cpp index 9301bce41b..025e0f4e21 100644 --- a/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_unions/SUPBOOK_bu.cpp +++ b/ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_unions/SUPBOOK_bu.cpp @@ -110,9 +110,9 @@ const bool SUPBOOK::loadContent(BinProcessor& proc) ExternDocName* docName = dynamic_cast(extern_name.body.get()); if(docName) { - if (docName->ixals > 0 && !supbook.rgst.empty()) + if (docName->ixals > 0 && docName->ixals < supbook.rgst.size()) { - name = supbook.rgst[docName->ixals]; + name = supbook.rgst[docName->ixals - 1]; } else { diff --git a/OfficeCryptReader/Test/Test.cpp b/OfficeCryptReader/Test/Test.cpp index 97c5627ef8..2903b1f274 100644 --- a/OfficeCryptReader/Test/Test.cpp +++ b/OfficeCryptReader/Test/Test.cpp @@ -21,6 +21,10 @@ int _tmain(int argc, _TCHAR* argv[]) { + std::wstring password = L"password"; + ECMACryptFile crypt_file; + bool result = false, bDataIntegrity = false; + std::wstring srcFileName = L"D:\\test\\_crypted\\test-111.docx"; std::wstring dstFileName = srcFileName + L"-mycrypt.docx"; std::wstring dstFileName2 = dstFileName + L".oox"; @@ -31,21 +35,12 @@ int _tmain(int argc, _TCHAR* argv[]) //std::wstring srcFileName = L"D:\\test\\_crypted\\test.docx"; //std::wstring dstFileName3 = srcFileName + L"-mycrypt1.docx"; - std::wstring password = L"574446f1-6aa0-860a-0296-787a87a214bb"; - - ECMACryptFile crypt_file; - bool result = false, bDataIntegrity = false; - - //result = crypt_file.DecryptOfficeFile(srcFileName, dstFileName, password, bDataIntegrity); - //result = crypt_file.EncryptOfficeFile(dstFileName, dstFileName2, password); - + //std::wstring srcFileName1 = L"D:\\test\\_crypted\\test-111.docx-ms.docx"; + //std::wstring dstFileName1 = srcFileName1 + L".oox"; + //result = crypt_file.DecryptOfficeFile(srcFileName1, dstFileName1, password, bDataIntegrity); + result = crypt_file.EncryptOfficeFile(srcFileName, dstFileName, password, L"123456789"); result = crypt_file.DecryptOfficeFile(dstFileName, dstFileName2, password, bDataIntegrity); - - COfficeFileFormatChecker fileChecker; - - std::wstring sDocumentID = fileChecker.getDocumentID(L"d:/test/_pdf/Test3-pdfa-my.pdf"); - + return 0; } - diff --git a/OfficeCryptReader/source/CryptTransform.cpp b/OfficeCryptReader/source/CryptTransform.cpp index 35f85baffb..743fae4909 100644 --- a/OfficeCryptReader/source/CryptTransform.cpp +++ b/OfficeCryptReader/source/CryptTransform.cpp @@ -36,6 +36,7 @@ #include "../../Common/3dParty/cryptopp/modes.h" #include "../../Common/3dParty/cryptopp/aes.h" +#include "../../Common/3dParty/cryptopp/des.h" #include "../../Common/3dParty/cryptopp/sha.h" #include "../../Common/3dParty/cryptopp/md5.h" #include "../../Common/3dParty/cryptopp/rsa.h" @@ -62,6 +63,8 @@ static const unsigned char encrKeyValueBlockKey[8] = { 0x14, 0x6e, 0x0b, 0xe static const unsigned char encrDataIntegritySaltBlockKey[8] = { 0x5f, 0xb2, 0xad, 0x01, 0x0c, 0xb9, 0xe1, 0xf6 }; static const unsigned char encrDataIntegrityHmacValueBlockKey[8] = { 0xa0, 0x67, 0x7f, 0x02, 0xb2, 0x2c, 0x84, 0x33 }; +#define PADDING_SIZE 16 + using namespace CryptoPP; class _buf @@ -280,6 +283,9 @@ _buf HashAppend(_buf & hashBuf, _buf & block, CRYPT_METHOD::_hashAlgorithm algo _buf GenerateAgileKey(_buf & salt, _buf & password, _buf & blockKey, int hashSize, int spin, CRYPT_METHOD::_hashAlgorithm algorithm) { + //if (hashSize < 8) + // blockKey = 8; + _buf pHashBuf = HashAppend(salt, password, algorithm); for (int i = 0; i < spin; i++) @@ -308,7 +314,7 @@ _buf GenerateOdfKey(_buf & pSalt, _buf & pPassword, int keySize, int spin, CRYPT return _buf(pKey.ptr, pKey.size); } -_buf GenerateHashKey(_buf & salt, _buf & password, int hashSize, int spin, CRYPT_METHOD::_hashAlgorithm algorithm, int block_index = 0) +_buf GenerateHashKey(_buf & salt, _buf & password, int hashSize, int keySize, int spin, CRYPT_METHOD::_hashAlgorithm algorithm, int block_index = 0) { _buf block ((unsigned char*)&block_index, 4, false); @@ -350,8 +356,15 @@ _buf GenerateHashKey(_buf & salt, _buf & password, int hashSize, int spin, CRYPT memcpy(pHashBuf3.ptr + 0, pHashBuf1.ptr, hashSize); memcpy(pHashBuf3.ptr + hashSize, pHashBuf2.ptr, hashSize); + CorrectHashSize(pHashBuf3, keySize, 0); + + if (keySize == 5) + CorrectHashSize(pHashBuf3, 16, 0); //40-bit crypt key !!! + return _buf(pHashBuf3.ptr, pHashBuf3.size); } +ARC4::Decryption rc4Decryption; // todooo -> in impl +ARC4::Encryption rc4Encryption; bool EncryptCipher(_buf & key, _buf & iv, _buf & data_inp, _buf & data_out, CRYPT_METHOD::_cipherAlgorithm algorithm, StreamTransformationFilter::BlockPaddingScheme padding = StreamTransformationFilter::PKCS_PADDING) @@ -362,10 +375,11 @@ bool EncryptCipher(_buf & key, _buf & iv, _buf & data_inp, _buf & data_out, CRYP } else if (algorithm == CRYPT_METHOD::RC4) { - data_out.ptr = new unsigned char[data_inp.size]; - data_out.size = data_inp.size; + if (!data_out.ptr) + { + data_out = _buf(data_inp.size); + } - ARC4::Encryption rc4Encryption(key.ptr, key.size); rc4Encryption.ProcessData(data_out.ptr, data_inp.ptr, data_inp.size); } @@ -374,6 +388,44 @@ bool EncryptCipher(_buf & key, _buf & iv, _buf & data_inp, _buf & data_out, CRYP CFB_Mode::Encryption encryption(key.ptr, key.size, iv.ptr); encryption.ProcessData(data_out.ptr, data_inp.ptr, data_inp.size); } + else if (algorithm == CRYPT_METHOD::DES_CBC) + { + if (!iv.ptr) + { + iv = _buf(16, true); + } + DES::Encryption desEncryption(key.ptr, key.size == 7 ? 8 : key.size); + StreamTransformation *modeEncryption = new CipherModeFinalTemplate_ExternalCipher(desEncryption, iv.ptr ); + if (!data_out.ptr) + { + data_out = _buf(data_inp.size); + } + StreamTransformationFilter stfEncryption(*modeEncryption, new ArraySink( data_out.ptr, data_out.size), padding); + + stfEncryption.Put( data_inp.ptr, data_inp.size ); + stfEncryption.MessageEnd(); + + delete modeEncryption; + } + else if (algorithm == CRYPT_METHOD::DES_ECB) + { + if (!iv.ptr) + { + iv = _buf(16, true); + } + DES::Encryption desEncryption(key.ptr, key.size == 7 ? 8 : key.size); + StreamTransformation *modeEncryption = new CipherModeFinalTemplate_ExternalCipher(desEncryption, iv.ptr ); + if (!data_out.ptr) + { + data_out = _buf(data_inp.size); + } + StreamTransformationFilter stfEncryption(*modeEncryption, new ArraySink( data_out.ptr, data_out.size), padding); + + stfEncryption.Put( data_inp.ptr, data_inp.size ); + stfEncryption.MessageEnd(); + + delete modeEncryption; + } else //AES { StreamTransformation *modeEncryption = NULL; @@ -413,8 +465,6 @@ bool EncryptCipher(_buf & key, _buf & iv, _buf & data_inp, _buf & data_out, CRYP return true; } -ARC4::Decryption rc4Decryption; // todooo -> in impl - bool DecryptCipher(_buf & key, _buf & iv, _buf & data_inp, _buf & data_out, CRYPT_METHOD::_cipherAlgorithm algorithm, StreamTransformationFilter::BlockPaddingScheme padding = StreamTransformationFilter::NO_PADDING) { @@ -436,6 +486,36 @@ bool DecryptCipher(_buf & key, _buf & iv, _buf & data_inp, _buf & data_out, CRY CFB_Mode::Decryption decryption(key.ptr, key.size, iv.ptr); decryption.ProcessData(data_out.ptr, data_inp.ptr, data_inp.size); } + else if (algorithm == CRYPT_METHOD::DES_CBC) + { + if (!iv.ptr) + { + iv = _buf(16, true); + } + DES::Decryption desDecryption(key.ptr, key.size == 7 ? 8 : key.size); + StreamTransformation *modeDecryption = new CipherModeFinalTemplate_ExternalCipher(desDecryption, iv.ptr ); + StreamTransformationFilter stfDecryptor(*modeDecryption, new ArraySink( data_out.ptr, data_out.size), padding); + + stfDecryptor.Put( data_inp.ptr, data_inp.size ); + stfDecryptor.MessageEnd(); + + delete modeDecryption; + } + else if (algorithm == CRYPT_METHOD::DES_ECB) + { + if (!iv.ptr) + { + iv = _buf(16, true); + } + DES::Decryption desDecryption(key.ptr, key.size == 7 ? 8 : key.size); + StreamTransformation *modeDecryption = new CipherModeFinalTemplate_ExternalCipher(desDecryption, iv.ptr ); + StreamTransformationFilter stfDecryptor(*modeDecryption, new ArraySink( data_out.ptr, data_out.size), padding); + + stfDecryptor.Put( data_inp.ptr, data_inp.size ); + stfDecryptor.MessageEnd(); + + delete modeDecryption; + } else //AES { StreamTransformation *modeDecryption = NULL; @@ -504,13 +584,20 @@ bool ECMADecryptor::SetPassword(std::wstring _password) _buf verifierInputKey = GenerateAgileKey( pSalt, pPassword, pInputBlockKey, cryptData.keySize, cryptData.spinCount, cryptData.hashAlgorithm ); _buf verifierHashKey = GenerateAgileKey( pSalt, pPassword, pValueBlockKey, cryptData.keySize, cryptData.spinCount, cryptData.hashAlgorithm ); + if (cryptData.cipherAlgorithm == CRYPT_METHOD::RC4) + { + rc4Decryption.SetKey(verifierInputKey.ptr, verifierInputKey.size); + } //-------------------------------------------- _buf decryptedVerifierHashInputBytes; DecryptCipher(verifierInputKey, pSalt, pEncVerInput, decryptedVerifierHashInputBytes, cryptData.cipherAlgorithm); //-------------------------------------------- _buf hashBuf = HashAppend(decryptedVerifierHashInputBytes, empty, cryptData.hashAlgorithm); //-------------------------------------------- - + if (cryptData.cipherAlgorithm == CRYPT_METHOD::RC4) + { + rc4Decryption.SetKey(verifierHashKey.ptr, verifierHashKey.size); + } _buf decryptedVerifierHashBytes; DecryptCipher(verifierHashKey, pSalt, pEncVerValue, decryptedVerifierHashBytes, cryptData.cipherAlgorithm); //-------------------------------------------- @@ -518,10 +605,7 @@ bool ECMADecryptor::SetPassword(std::wstring _password) } else { - _buf verifierKey = GenerateHashKey(pSalt, pPassword, cryptData.hashSize, cryptData.spinCount, cryptData.hashAlgorithm); - CorrectHashSize(verifierKey, cryptData.keySize, 0); - if (cryptData.keySize == 5) - CorrectHashSize(verifierKey, 16, 0); //40-bit crypt key !!! + _buf verifierKey = GenerateHashKey(pSalt, pPassword, cryptData.hashSize, cryptData.keySize, cryptData.spinCount, cryptData.hashAlgorithm); if (cryptData.cipherAlgorithm == CRYPT_METHOD::RC4) { @@ -538,7 +622,7 @@ bool ECMADecryptor::SetPassword(std::wstring _password) _buf decryptedVerifierHashBytes; DecryptCipher(verifierKey, pSalt, pEncVerValue, decryptedVerifierHashBytes, cryptData.cipherAlgorithm); - bVerify = (decryptedVerifierHashBytes==hashBuf); + bVerify = (decryptedVerifierHashBytes == hashBuf); } return bVerify; } @@ -587,11 +671,8 @@ void ECMADecryptor::Decrypt(char* data , const size_t size, const unsigned long _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); + _buf hashKey = GenerateHashKey(pSalt, pPassword, cryptData.hashSize, cryptData.keySize, cryptData.spinCount, cryptData.hashAlgorithm, block_index); - if (cryptData.keySize == 5) CorrectHashSize(hashKey, 16, 0); //40-bit crypt key !!! - rc4Decryption.SetKey(hashKey.ptr, hashKey.size); } @@ -681,6 +762,10 @@ void ECMADecryptor::Decrypt(unsigned char* data_inp, int size, unsigned char*& _buf agileKey = GenerateAgileKey( pSalt, pPassword, pBlockKey, cryptData.keySize, cryptData.spinCount, cryptData.hashAlgorithm); + if (cryptData.cipherAlgorithm == CRYPT_METHOD::RC4) + { + rc4Decryption.SetKey(agileKey.ptr, agileKey.size); + } _buf pDecryptedKey; DecryptCipher( agileKey, pSalt, pKeyValue, pDecryptedKey, cryptData.cipherAlgorithm); @@ -688,6 +773,10 @@ void ECMADecryptor::Decrypt(unsigned char* data_inp, int size, unsigned char*& int i = start_iv_block, sz = 4096, pos = 0;//aes block size = 4096 + if (cryptData.cipherAlgorithm == CRYPT_METHOD::RC4) + { + rc4Decryption.SetKey(pDecryptedKey.ptr, pDecryptedKey.size); + } while (pos < size) { if (pos + sz > size) @@ -708,14 +797,10 @@ void ECMADecryptor::Decrypt(unsigned char* data_inp, int size, unsigned char*& } else { - _buf hashKey = GenerateHashKey(pSalt, pPassword, cryptData.hashSize, cryptData.spinCount, cryptData.hashAlgorithm, start_iv_block); - CorrectHashSize(hashKey, cryptData.keySize, 0); + _buf hashKey = GenerateHashKey(pSalt, pPassword, cryptData.hashSize, cryptData.keySize, cryptData.spinCount, cryptData.hashAlgorithm, start_iv_block); if (cryptData.cipherAlgorithm == CRYPT_METHOD::RC4) - { - if (cryptData.keySize == 5) - CorrectHashSize(hashKey, 16, 0); //40-bit crypt key !!! - + { rc4Decryption.SetKey(hashKey.ptr, hashKey.size); } @@ -759,40 +844,85 @@ void ECMAEncryptor::SetPassword(std::wstring _password) //--------- _buf pPassword (password); _buf empty (NULL, 0, false); - - _buf pBlockKey ((unsigned char*)encrKeyValueBlockKey, 8); - _buf pInputBlockKey ((unsigned char*)encrVerifierHashInputBlockKey, 8); - _buf pValueBlockKey ((unsigned char*)encrVerifierHashValueBlockKey, 8); - + _buf pSalt (seed_salt.data(), seed_salt.size()); _buf pDataSalt (seed_datasalt.data(), seed_datasalt.size()); _buf pDecryptedKey (seed_key.data(), seed_key.size()); //------------------------------------------------------------------------------------------------ - _buf agileKey = GenerateAgileKey( pSalt, pPassword, pBlockKey, cryptData.keySize, cryptData.spinCount, cryptData.hashAlgorithm); + if (cryptData.bAgile == true) + { + _buf pBlockKey ((unsigned char*)encrKeyValueBlockKey, 8); + _buf pInputBlockKey ((unsigned char*)encrVerifierHashInputBlockKey, 8); + _buf pValueBlockKey ((unsigned char*)encrVerifierHashValueBlockKey, 8); + + _buf agileKey = GenerateAgileKey( pSalt, pPassword, pBlockKey, cryptData.keySize, cryptData.spinCount, cryptData.hashAlgorithm); - _buf pKeyValue; - EncryptCipher( agileKey, pSalt, pDecryptedKey, pKeyValue, cryptData.cipherAlgorithm); - -//-------------------------------------------- - _buf decryptedVerifierHashInputBytes(seed_verify.data(), seed_verify.size()); - _buf verifierInputKey = GenerateAgileKey( pSalt, pPassword, pInputBlockKey, cryptData.keySize, cryptData.spinCount, cryptData.hashAlgorithm ); - - _buf pEncVerInput; - EncryptCipher( verifierInputKey, pSalt, decryptedVerifierHashInputBytes, pEncVerInput, cryptData.cipherAlgorithm); -//-------------------------------------------- + if (cryptData.cipherAlgorithm == CRYPT_METHOD::RC4) + { + rc4Encryption.SetKey(agileKey.ptr, agileKey.size); + } + _buf pKeyValue; + EncryptCipher( agileKey, pSalt, pDecryptedKey, pKeyValue, cryptData.cipherAlgorithm); + + //-------------------------------------------- + _buf decryptedVerifierHashInputBytes(seed_verify.data(), seed_verify.size()); + _buf verifierInputKey = GenerateAgileKey( pSalt, pPassword, pInputBlockKey, cryptData.keySize, cryptData.spinCount, cryptData.hashAlgorithm ); + + if (cryptData.cipherAlgorithm == CRYPT_METHOD::RC4) + { + rc4Encryption.SetKey(verifierInputKey.ptr, verifierInputKey.size); + } + _buf pEncVerInput; + EncryptCipher( verifierInputKey, pSalt, decryptedVerifierHashInputBytes, pEncVerInput, cryptData.cipherAlgorithm); + //-------------------------------------------- - _buf decryptedVerifierHashBytes = HashAppend(decryptedVerifierHashInputBytes, empty, cryptData.hashAlgorithm); - _buf verifierHashKey = GenerateAgileKey(pSalt, pPassword, pValueBlockKey, cryptData.keySize, cryptData.spinCount, cryptData.hashAlgorithm); - - _buf pEncVerValue; - EncryptCipher( verifierHashKey, pSalt, decryptedVerifierHashBytes, pEncVerValue, cryptData.cipherAlgorithm); + _buf decryptedVerifierHashBytes = HashAppend(decryptedVerifierHashInputBytes, empty, cryptData.hashAlgorithm); + _buf verifierHashKey = GenerateAgileKey(pSalt, pPassword, pValueBlockKey, cryptData.keySize, cryptData.spinCount, cryptData.hashAlgorithm); + + if (cryptData.cipherAlgorithm == CRYPT_METHOD::RC4) + { + rc4Encryption.SetKey(verifierHashKey.ptr, verifierHashKey.size); + } + else if (decryptedVerifierHashBytes.size % PADDING_SIZE != 0) + { + CorrectHashSize(decryptedVerifierHashBytes, (decryptedVerifierHashBytes.size / PADDING_SIZE + 1) * PADDING_SIZE, 0); + } + _buf pEncVerValue; + EncryptCipher( verifierHashKey, pSalt, decryptedVerifierHashBytes, pEncVerValue, cryptData.cipherAlgorithm); - cryptData.saltValue = std::string((char*)pSalt.ptr, pSalt.size); - cryptData.dataSaltValue = std::string((char*)pDataSalt.ptr, pDataSalt.size); - cryptData.encryptedKeyValue = std::string((char*)pKeyValue.ptr, pKeyValue.size); - cryptData.encryptedVerifierInput = std::string((char*)pEncVerInput.ptr, pEncVerInput.size); - cryptData.encryptedVerifierValue = std::string((char*)pEncVerValue.ptr, pEncVerValue.size); + cryptData.saltValue = std::string((char*)pSalt.ptr, pSalt.size); + cryptData.dataSaltValue = std::string((char*)pDataSalt.ptr, pDataSalt.size); + cryptData.encryptedKeyValue = std::string((char*)pKeyValue.ptr, pKeyValue.size); + cryptData.encryptedVerifierInput = std::string((char*)pEncVerInput.ptr, pEncVerInput.size); + cryptData.encryptedVerifierValue = std::string((char*)pEncVerValue.ptr, pEncVerValue.size); + } + else + { + _buf verifierKey = GenerateHashKey(pSalt, pPassword, cryptData.hashSize, cryptData.keySize, cryptData.spinCount, cryptData.hashAlgorithm); + + if (cryptData.cipherAlgorithm == CRYPT_METHOD::RC4) + { + rc4Encryption.SetKey(verifierKey.ptr, verifierKey.size); + } + _buf decryptedVerInput(seed_verify.data(), seed_verify.size()); + + _buf pEncVerInput; + EncryptCipher( verifierKey, pSalt, decryptedVerInput, pEncVerInput, cryptData.cipherAlgorithm); + + _buf hashBuf = HashAppend(decryptedVerInput, empty, cryptData.hashAlgorithm); + if (cryptData.cipherAlgorithm != CRYPT_METHOD::RC4 && hashBuf.size % PADDING_SIZE != 0) + { + CorrectHashSize(hashBuf, (hashBuf.size / PADDING_SIZE + 1) * PADDING_SIZE, 0); + } + + _buf pEncVerValue; + EncryptCipher( verifierKey, pSalt, hashBuf, pEncVerValue, cryptData.cipherAlgorithm); + + cryptData.saltValue = std::string((char*)pSalt.ptr, pSalt.size); + cryptData.encryptedVerifierInput = std::string((char*)pEncVerInput.ptr, pEncVerInput.size); + cryptData.encryptedVerifierValue = std::string((char*)pEncVerValue.ptr, pEncVerValue.size); + } } void ECMAEncryptor::SetCryptData(_ecmaCryptData & data) @@ -823,6 +953,11 @@ void ECMAEncryptor::UpdateDataIntegrity(unsigned char* data, int size) //---- _buf agileKey = GenerateAgileKey( pSalt, pPassword, pBlockKey, cryptData.keySize, cryptData.spinCount, cryptData.hashAlgorithm); + if (cryptData.cipherAlgorithm == CRYPT_METHOD::RC4) + { + rc4Encryption.SetKey(agileKey.ptr, agileKey.size); + } + _buf secretKey; DecryptCipher( agileKey, pSalt, pKeyValue, secretKey, cryptData.cipherAlgorithm); @@ -844,16 +979,28 @@ void ECMAEncryptor::UpdateDataIntegrity(unsigned char* data, int size) std::string sData((char*)data, size); _buf hmac = Hmac(pSaltHmac, cryptData.hashAlgorithm, sData); + if (cryptData.cipherAlgorithm == CRYPT_METHOD::RC4) + { + rc4Encryption.SetKey(secretKey.ptr, secretKey.size); + } + if (pSaltHmac.size % PADDING_SIZE != 0) + { + CorrectHashSize(pSaltHmac, (pSaltHmac.size / PADDING_SIZE + 1) * PADDING_SIZE, 0); + } _buf pEncHmacKey; EncryptCipher(secretKey, iv1, pSaltHmac, pEncHmacKey, cryptData.cipherAlgorithm); + if (hmac.size % PADDING_SIZE != 0) + { + CorrectHashSize(hmac, (hmac.size / PADDING_SIZE + 1) * PADDING_SIZE, 0); + } _buf pEncHmacValue; EncryptCipher(secretKey, iv2, hmac, pEncHmacValue, cryptData.cipherAlgorithm); cryptData.encryptedHmacKey = std::string((char*)pEncHmacKey.ptr, pEncHmacKey.size); cryptData.encryptedHmacValue = std::string((char*)pEncHmacValue.ptr, pEncHmacValue.size); } -#define PADDING_SIZE 16 // 8 + int ECMAEncryptor::Encrypt(unsigned char* data_inp_ptr, int size, unsigned char*& data_out_ptr) { data_out_ptr = NULL; @@ -863,7 +1010,8 @@ int ECMAEncryptor::Encrypt(unsigned char* data_inp_ptr, int size, unsigned char* _buf empty (NULL, 0, false); int size_out = size; - if (size_out % PADDING_SIZE != 0) + + if (cryptData.cipherAlgorithm != CRYPT_METHOD::RC4 && size_out % PADDING_SIZE != 0) size_out = (size_out / PADDING_SIZE + 1) * PADDING_SIZE; data_out_ptr = new unsigned char[size_out + PADDING_SIZE]; // real size + padding + size for realsize @@ -873,63 +1021,90 @@ int ECMAEncryptor::Encrypt(unsigned char* data_inp_ptr, int size, unsigned char* unsigned char* data_inp = data_inp_ptr; unsigned char* data_out = data_out_ptr + 8; - - _buf pBlockKey ((unsigned char*)encrKeyValueBlockKey, 8); - _buf pDataSalt (cryptData.dataSaltValue); - _buf pKeyValue (cryptData.encryptedKeyValue); -//------------------------------------------------------------------------------------------------ - _buf agileKey = GenerateAgileKey( pSalt, pPassword, pBlockKey, cryptData.keySize, cryptData.spinCount, cryptData.hashAlgorithm); - - _buf pDecryptedKey; - DecryptCipher( agileKey, pSalt, pKeyValue, pDecryptedKey, cryptData.cipherAlgorithm); - -//------------------------------------------------------------------------------------------------- - _buf iv(cryptData.blockSize, true); - - int i = 0, sz = 4096, enc_size = 0; - - while (enc_size < size) - { - if (enc_size + sz > size) - { - sz = size - enc_size; - } + if (cryptData.bAgile) + { + _buf pBlockKey ((unsigned char*)encrKeyValueBlockKey, 8); + _buf pDataSalt (cryptData.dataSaltValue); + _buf pKeyValue (cryptData.encryptedKeyValue); - _buf pIndex((unsigned char*)&i, 4); - iv = HashAppend(pDataSalt, pIndex, cryptData.hashAlgorithm); + //------------------------------------------------------------------------------------------------ + _buf agileKey = GenerateAgileKey( pSalt, pPassword, pBlockKey, cryptData.keySize, cryptData.spinCount, cryptData.hashAlgorithm); - CorrectHashSize(iv, cryptData.blockSize, 0x36); + if (cryptData.cipherAlgorithm == CRYPT_METHOD::RC4) + { + rc4Decryption.SetKey(agileKey.ptr, agileKey.size); + } + _buf pDecryptedKey; + DecryptCipher( agileKey, pSalt, pKeyValue, pDecryptedKey, cryptData.cipherAlgorithm); - if (sz < 4096) + if (cryptData.cipherAlgorithm == CRYPT_METHOD::RC4) { - _buf pInp(4096); - memcpy(pInp.ptr, data_inp, sz ); - pInp.size = sz; - _buf pOut(4096); - - EncryptCipher(pDecryptedKey, iv, pInp, pOut, cryptData.cipherAlgorithm); - - if (sz % PADDING_SIZE != 0) - sz = (sz / PADDING_SIZE + 1) * PADDING_SIZE; - - memcpy(data_out, pOut.ptr, sz); - + rc4Encryption.SetKey(pDecryptedKey.ptr, agileKey.size); } - else + //------------------------------------------------------------------------------------------------- + _buf iv(cryptData.blockSize, true); + + int i = 0, sz = 4096, enc_size = 0; + + while (enc_size < size) { - _buf pInp(data_inp, sz, false); - _buf pOut(data_out, sz, false); + if (enc_size + sz > size) + { + sz = size - enc_size; + } - EncryptCipher(pDecryptedKey, iv, pInp, pOut, cryptData.cipherAlgorithm); - } - data_inp += sz; - data_out += sz; + _buf pIndex((unsigned char*)&i, 4); + iv = HashAppend(pDataSalt, pIndex, cryptData.hashAlgorithm); - enc_size += sz; i++; + CorrectHashSize(iv, cryptData.blockSize, 0x36); + + if (sz < 4096) + { + _buf pInp(4096); + memcpy(pInp.ptr, data_inp, sz ); + pInp.size = sz; + _buf pOut(4096); + + EncryptCipher(pDecryptedKey, iv, pInp, pOut, cryptData.cipherAlgorithm); + + if (sz % PADDING_SIZE != 0) + sz = (sz / PADDING_SIZE + 1) * PADDING_SIZE; + + memcpy(data_out, pOut.ptr, sz); + + } + else + { + _buf pInp(data_inp, sz, false); + _buf pOut(data_out, sz, false); + + EncryptCipher(pDecryptedKey, iv, pInp, pOut, cryptData.cipherAlgorithm); + } + data_inp += sz; + data_out += sz; + + enc_size += sz; i++; + } + return enc_size + 8; } + else + { + _buf hashKey = GenerateHashKey(pSalt, pPassword, cryptData.hashSize, cryptData.keySize, cryptData.spinCount, cryptData.hashAlgorithm); + + if (cryptData.cipherAlgorithm == CRYPT_METHOD::RC4) + { + rc4Decryption.SetKey(hashKey.ptr, hashKey.size); + rc4Encryption.SetKey(hashKey.ptr, hashKey.size); + } + + _buf pInp(data_inp, size, false); + _buf pOut(data_out, size_out, false); - return enc_size + 8; + EncryptCipher(hashKey, empty, pInp, pOut, cryptData.cipherAlgorithm/*, StreamTransformationFilter::ZEROS_PADDING*/); + + return size_out + 8; + } } //----------------------------------------------------------------------------------------------------------- ODFDecryptor::ODFDecryptor() diff --git a/OfficeCryptReader/source/CryptTransform.h b/OfficeCryptReader/source/CryptTransform.h index 5b3a485a34..94a4a559b2 100644 --- a/OfficeCryptReader/source/CryptTransform.h +++ b/OfficeCryptReader/source/CryptTransform.h @@ -55,7 +55,9 @@ namespace CRYPT_METHOD AES_CBC, AES_CFB, AES_ECB, - Blowfish_CFB + Blowfish_CFB, + DES_CBC, + DES_ECB }; } namespace CRYPT diff --git a/OfficeCryptReader/source/ECMACryptFile.cpp b/OfficeCryptReader/source/ECMACryptFile.cpp index a616e19417..c6d8c514b3 100644 --- a/OfficeCryptReader/source/ECMACryptFile.cpp +++ b/OfficeCryptReader/source/ECMACryptFile.cpp @@ -46,7 +46,8 @@ using namespace CRYPT; -#define GETBIT(from, num) ((from & (1 << num)) != 0) +#define GETBIT(from, num) ((from & (1 << num)) != 0) +#define SETBIT(to, num, setorclear) {setorclear ? to |= (1 << num) : to &= ~(1 << num);} #define WritingElement_ReadAttributes_Start(Reader) \ if ( Reader.GetAttributesCount() <= 0 )\ @@ -288,15 +289,26 @@ bool ReadXmlEncryptionInfo(const std::string & xml_string, _ecmaCryptData & cryp if (keyData.cipherAlgorithm == "AES") { - if (keyData.cipherChaining == "ChainingModeCBC") cryptData.cipherAlgorithm = CRYPT_METHOD::AES_CBC; + cryptData.cipherAlgorithm = CRYPT_METHOD::AES_CBC; + //if (keyData.cipherChaining == "ChainingModeCBC") cryptData.cipherAlgorithm = CRYPT_METHOD::AES_CBC; if (keyData.cipherChaining == "ChainingModeCFB") cryptData.cipherAlgorithm = CRYPT_METHOD::AES_CFB; } - - if (keyData.hashAlgorithm == "SHA1") cryptData.hashAlgorithm = CRYPT_METHOD::SHA1; - if (keyData.hashAlgorithm == "SHA224") cryptData.hashAlgorithm = CRYPT_METHOD::SHA224; - if (keyData.hashAlgorithm == "SHA256") cryptData.hashAlgorithm = CRYPT_METHOD::SHA256; - if (keyData.hashAlgorithm == "SHA384") cryptData.hashAlgorithm = CRYPT_METHOD::SHA384; - if (keyData.hashAlgorithm == "SHA512") cryptData.hashAlgorithm = CRYPT_METHOD::SHA512; + else if (keyData.cipherAlgorithm == "RC4") + { + cryptData.cipherAlgorithm = CRYPT_METHOD::RC4; + } + else if (keyData.cipherAlgorithm == "DES") + { + cryptData.cipherAlgorithm = CRYPT_METHOD::DES_CBC; + //if (keyData.cipherChaining == "ChainingModeCBC") cryptData.cipherAlgorithm = CRYPT_METHOD::DES_CBC; + if (keyData.cipherChaining == "ChainingModeECB") cryptData.cipherAlgorithm = CRYPT_METHOD::DES_ECB; + } + if (keyData.hashAlgorithm == "SHA1") cryptData.hashAlgorithm = CRYPT_METHOD::SHA1; + else if (keyData.hashAlgorithm == "SHA224") cryptData.hashAlgorithm = CRYPT_METHOD::SHA224; + else if (keyData.hashAlgorithm == "SHA256") cryptData.hashAlgorithm = CRYPT_METHOD::SHA256; + else if (keyData.hashAlgorithm == "SHA384") cryptData.hashAlgorithm = CRYPT_METHOD::SHA384; + else if (keyData.hashAlgorithm == "SHA512") cryptData.hashAlgorithm = CRYPT_METHOD::SHA512; + else if (keyData.hashAlgorithm == "MD5") cryptData.hashAlgorithm = CRYPT_METHOD::MD5; return true; } @@ -315,12 +327,33 @@ bool WriteXmlEncryptionInfo(const _ecmaCryptData & cryptData, std::string & xml_ keyData.keyBits = std::to_string(cryptData.keySize * 8); keyData.saltValue = EncodeBase64(cryptData.dataSaltValue); - keyData.cipherAlgorithm = "AES"; - - if (keyData.cipherAlgorithm == "AES") + switch(cryptData.cipherAlgorithm) { - if (cryptData.cipherAlgorithm == CRYPT_METHOD::AES_CBC) keyData.cipherChaining = "ChainingModeCBC"; - if (cryptData.cipherAlgorithm == CRYPT_METHOD::AES_CFB) keyData.cipherChaining = "ChainingModeCFB"; + case CRYPT_METHOD::RC4: + keyData.cipherAlgorithm = "RC4"; + break; + case CRYPT_METHOD::AES_CBC: + keyData.cipherAlgorithm = "AES"; + keyData.cipherChaining = "ChainingModeCBC"; + break; + case CRYPT_METHOD::AES_ECB: + keyData.cipherAlgorithm = "AES"; + keyData.cipherChaining = "ChainingModeECB"; + break; + case CRYPT_METHOD::AES_CFB: + keyData.cipherAlgorithm = "AES"; + keyData.cipherChaining = "ChainingModeCFB"; + break; + case CRYPT_METHOD::DES_CBC: + keyData.cipherAlgorithm = "DES"; + keyData.cipherChaining = "ChainingModeCBC"; + break; + case CRYPT_METHOD::DES_ECB: + keyData.cipherAlgorithm = "DES"; + keyData.cipherChaining = "ChainingModeECB"; + break; + break; + } switch(cryptData.hashAlgorithm) @@ -330,6 +363,7 @@ bool WriteXmlEncryptionInfo(const _ecmaCryptData & cryptData, std::string & xml_ case CRYPT_METHOD::SHA256: keyData.hashAlgorithm = "SHA256"; break; case CRYPT_METHOD::SHA384: keyData.hashAlgorithm = "SHA384"; break; case CRYPT_METHOD::SHA512: keyData.hashAlgorithm = "SHA512"; break; + case CRYPT_METHOD::MD5: keyData.hashAlgorithm = "MD5"; break; } std::vector<_keyEncryptor> keyEncryptors; @@ -360,7 +394,12 @@ bool WriteXmlEncryptionInfo(const _ecmaCryptData & cryptData, std::string & xml_ CP_XML_ATTR("keyBits", keyData.keyBits); CP_XML_ATTR("hashSize", keyData.hashSize); CP_XML_ATTR("cipherAlgorithm", keyData.cipherAlgorithm); - CP_XML_ATTR("cipherChaining", keyData.cipherChaining); + + if (false == keyData.cipherChaining.empty()) + { + CP_XML_ATTR("cipherChaining", keyData.cipherChaining); + } + CP_XML_ATTR("hashAlgorithm", keyData.hashAlgorithm); CP_XML_ATTR("saltValue", keyData.saltValue); } @@ -400,7 +439,105 @@ bool WriteXmlEncryptionInfo(const _ecmaCryptData & cryptData, std::string & xml_ return true; } +bool WriteStandartEncryptionInfo(unsigned char* data, int &size, _ecmaCryptData & cryptData) +{ + if (!data || size < 1) return false; + MemoryStream mem_stream(data, size, false); + _UINT32 SizeHeader = 0, Flags = 0, SizeExtra = 0, AlgID = 0, AlgIDHash = 0, KeySize = 0, ProviderType = 0, Reserved1 = 0, Reserved2 = 0; + + bool fCryptoAPI = true, fDocProps = false, fExternal = false, fAES = cryptData.cipherAlgorithm != CRYPT_METHOD::RC4; + + SETBIT(Flags, 2, fCryptoAPI); + SETBIT(Flags, 3, fDocProps); + SETBIT(Flags, 4, fExternal); + SETBIT(Flags, 5, fAES); + + mem_stream.WriteUInt32(SizeHeader); + + KeySize = (cryptData.keySize == 5) ? 0 : cryptData.keySize * 8; + + std::string provider;// to utf16 + switch(cryptData.cipherAlgorithm) + { + case CRYPT_METHOD::RC4: + { + ProviderType = 0x0001; + AlgID = 0x6801; + }break; + case CRYPT_METHOD::DES_ECB: + case CRYPT_METHOD::DES_CBC: + { + ProviderType = 0;//0x0018; + AlgID = 0x6601; + }break; + case CRYPT_METHOD::AES_ECB: + case CRYPT_METHOD::AES_CBC: + { + ProviderType = 0x0018; + switch(KeySize) + { + case 128: AlgID = 0x660E; break; + case 192: AlgID = 0x660F; break; + case 256: AlgID = 0x6610; break; + } + break; + }break; + } + //ProviderType = 0x0018; + + switch(ProviderType) + { + case 0x0001: provider = "Microsoft Strong Cryptographic Provider"; break; + case 0x0018: provider = "Microsoft Enhanced RSA and AES Cryptographic Provider"; break; + } + switch(cryptData.hashAlgorithm) + { + case CRYPT_METHOD::MD5: AlgIDHash = 0x8003; break; + case CRYPT_METHOD::SHA1: AlgIDHash = 0x8004; break; + case CRYPT_METHOD::SHA256: AlgIDHash = 0x8004; break; + case CRYPT_METHOD::SHA384: AlgIDHash = 0x800D; break; + case CRYPT_METHOD::SHA512: AlgIDHash = 0x800E; break; + } + + mem_stream.WriteUInt32(Flags); + mem_stream.WriteUInt32(SizeExtra); + mem_stream.WriteUInt32(AlgID); + mem_stream.WriteUInt32(AlgIDHash); + mem_stream.WriteUInt32(KeySize); + mem_stream.WriteUInt32(ProviderType); + mem_stream.WriteUInt32(Reserved1); + mem_stream.WriteUInt32(Reserved2); + + for (size_t i = 0; i < provider.length(); ++i) + { + mem_stream.WriteByte((unsigned char)provider[i]); + mem_stream.WriteByte((unsigned char)0); + } + mem_stream.WriteByte((unsigned char)0); //null terminate + mem_stream.WriteByte((unsigned char)0); + + SizeHeader = mem_stream.GetPosition() - 4; + +//EncryptionVerifier + mem_stream.WriteUInt32((_UINT32)cryptData.saltSize); + + mem_stream.WriteBytes((unsigned char*)cryptData.saltValue.c_str(), cryptData.saltSize); + + mem_stream.WriteBytes((unsigned char*)cryptData.encryptedVerifierInput.c_str(), 0x10); + + mem_stream.WriteUInt32((_UINT32)cryptData.hashSize); + + //int szEncryptedVerifierHash = (ProviderType == 0x0001) ? 0x14 : 0x20; //RC4 | AES(DES) .. md5? + mem_stream.WriteBytes((unsigned char*)cryptData.encryptedVerifierValue.c_str(), cryptData.encryptedVerifierValue.length()/*szEncryptedVerifierHash*/); + + size = mem_stream.GetPosition(); + + mem_stream.Seek(0); + mem_stream.WriteUInt32(SizeHeader); + + return true; +} bool ReadStandartEncryptionInfo(unsigned char* data, int size, _ecmaCryptData & cryptData) { if (!data || size < 1) return false; @@ -445,21 +582,41 @@ bool ReadStandartEncryptionInfo(unsigned char* data, int size, _ecmaCryptData & cryptData.hashSize = mem_stream.ReadUInt32(); - int szEncryptedVerifierHash = (ProviderType == 0x0001) ? 0x14 : 0x20; - cryptData.encryptedVerifierValue = std::string((char*)data + mem_stream.GetPosition(), szEncryptedVerifierHash); + unsigned long szEncryptedVerifierHash = (ProviderType == 0x0001) ? 0x14 : 0x20; // RC4 | AES(DES) + unsigned long szEncryptedVerifierHashMax = mem_stream.GetSize() - mem_stream.GetPosition(); + + cryptData.encryptedVerifierValue = std::string((char*)data + mem_stream.GetPosition(), max(szEncryptedVerifierHash, szEncryptedVerifierHashMax)); mem_stream.ReadBytes(szEncryptedVerifierHash, false); pos = mem_stream.GetPosition(); //------------------------------------------------------------------------------------------ - cryptData.hashAlgorithm = CRYPT_METHOD::SHA1; //by AlgIDHash -> 0x0000 || 0x8004 - cryptData.spinCount = 50000; + switch(AlgIDHash) + { + case 0x8003: + cryptData.hashAlgorithm = CRYPT_METHOD::MD5; break; + case 0x0000: + case 0x8004: + cryptData.hashAlgorithm = CRYPT_METHOD::SHA1; break; + case 0x800C: + cryptData.hashAlgorithm = CRYPT_METHOD::SHA256; break; + case 0x800D: + cryptData.hashAlgorithm = CRYPT_METHOD::SHA384; break; + case 0x800E: + cryptData.hashAlgorithm = CRYPT_METHOD::SHA512; break; + } + cryptData.spinCount = 50000; switch(AlgID) { case 0x6801: cryptData.cipherAlgorithm = CRYPT_METHOD::RC4; - cryptData.keySize = KeySize / 8; + if (KeySize == 0) cryptData.keySize = 5; //40 bit + else cryptData.keySize = KeySize / 8; + break; + case 0x6601: + cryptData.cipherAlgorithm = CRYPT_METHOD::DES_ECB; + cryptData.keySize = 8; break; case 0x660E: cryptData.cipherAlgorithm = CRYPT_METHOD::AES_ECB; @@ -488,12 +645,53 @@ bool ECMACryptFile::EncryptOfficeFile(const std::wstring &file_name_inp, const s { _ecmaCryptData cryptData; - cryptData.bAgile = true; - cryptData.hashAlgorithm = CRYPT_METHOD::SHA512; - cryptData.keySize = 0x20; - cryptData.hashSize = 0x40; - cryptData.blockSize = 0x10; - cryptData.saltSize = 0x10; + //cryptData.bAgile = true; + //cryptData.cipherAlgorithm = CRYPT_METHOD::DES_CBC; + ////cryptData.hashAlgorithm = CRYPT_METHOD::SHA512; + ////cryptData.keySize = 0x08; + ////cryptData.hashSize = 0x40; + ////cryptData.blockSize = 0x10; + ////cryptData.saltSize = 0x10; + //cryptData.hashAlgorithm = CRYPT_METHOD::SHA1; + //cryptData.keySize = 0x08; + //cryptData.hashSize = 0x14; + //cryptData.blockSize = 0x10; + //cryptData.saltSize = 0x10; + + cryptData.bAgile = true; + cryptData.cipherAlgorithm = CRYPT_METHOD::AES_CBC; + cryptData.hashAlgorithm = CRYPT_METHOD::SHA512; + cryptData.keySize = 0x20; + cryptData.hashSize = 0x40; + cryptData.blockSize = 0x10; + cryptData.saltSize = 0x10; + + //cryptData.bAgile = false; + //cryptData.cipherAlgorithm = CRYPT_METHOD::AES_ECB; + //cryptData.hashAlgorithm = CRYPT_METHOD::SHA1; + //cryptData.keySize = 0x10; + //cryptData.hashSize = 0x14; + //cryptData.blockSize = 0x10; + //cryptData.saltSize = 0x10; + //cryptData.spinCount = 50000; + + //cryptData.bAgile = false; + //cryptData.cipherAlgorithm = CRYPT_METHOD::RC4; + //cryptData.hashAlgorithm = CRYPT_METHOD::SHA1; + //cryptData.keySize = 7; + //cryptData.hashSize = 0x14; + //cryptData.blockSize = 0x10; + //cryptData.saltSize = 0x10; + //cryptData.spinCount = 50000; + + //cryptData.bAgile = false; + //cryptData.cipherAlgorithm = CRYPT_METHOD::DES_ECB; + //cryptData.hashAlgorithm = CRYPT_METHOD::SHA1; + //cryptData.keySize = 0x08; + //cryptData.hashSize = 0x14; + //cryptData.blockSize = 0x10; + //cryptData.saltSize = 0x10; + //cryptData.spinCount = 50000; ECMAEncryptor cryptor; @@ -539,22 +737,53 @@ bool ECMACryptFile::EncryptOfficeFile(const std::wstring &file_name_inp, const s cryptor.GetCryptData(cryptData); - std::string strXml; - WriteXmlEncryptionInfo(cryptData, strXml); + if (cryptData.bAgile) + { + _UINT16 VersionInfoMajor = 0x0004, VersionInfoMinor = 0x0004; //agile + + pStream->write((unsigned char*)&VersionInfoMajor, 2); + pStream->write((unsigned char*)&VersionInfoMinor, 2); - _UINT16 VersionInfoMajor = 0x0004, VersionInfoMinor = 0x0004; //agile standart + _UINT32 nEncryptionInfoFlags = 64; + pStream->write((unsigned char*)&nEncryptionInfoFlags, 4); + + std::string strXml; + WriteXmlEncryptionInfo(cryptData, strXml); + + pStream->write((unsigned char*)strXml.c_str(), strXml.length()); + + pStream->flush(); + delete pStream; + } + else + { + _UINT16 VersionInfoMajor = 0x0004, VersionInfoMinor = 0x0002; // standart - pStream->write((unsigned char*)&VersionInfoMajor, 2); - pStream->write((unsigned char*)&VersionInfoMinor, 2); + pStream->write((unsigned char*)&VersionInfoMajor, 2); + pStream->write((unsigned char*)&VersionInfoMinor, 2); - _UINT32 nEncryptionInfoFlags = 64; - pStream->write((unsigned char*)&nEncryptionInfoFlags, 4); - - pStream->write((unsigned char*)strXml.c_str(), strXml.length()); - - pStream->flush(); - delete pStream; -//------------------------------------------------------------------- + _UINT32 nEncryptionInfoFlags = 0; + bool fCryptoAPI = true, fDocProps = false, fExternal = false, fAES = cryptData.cipherAlgorithm != CRYPT_METHOD::RC4; + + SETBIT(nEncryptionInfoFlags, 2, fCryptoAPI); + SETBIT(nEncryptionInfoFlags, 3, fDocProps); + SETBIT(nEncryptionInfoFlags, 4, fExternal); + SETBIT(nEncryptionInfoFlags, 5, fAES); + + pStream->write((unsigned char*)&nEncryptionInfoFlags, 4); + + int nEncryptionInfoSize = 4096; + unsigned char* byteEncryptionInfo = new unsigned char[nEncryptionInfoSize]; + + WriteStandartEncryptionInfo(byteEncryptionInfo, nEncryptionInfoSize, cryptData); + + pStream->write(byteEncryptionInfo, nEncryptionInfoSize); + delete []byteEncryptionInfo; + + pStream->flush(); + delete pStream; + } + //------------------------------------------------------------------- pStream = new POLE::Stream(pStorage, L"EncryptedPackage", true, lengthData); pStream->write(data_out, lengthData); @@ -651,10 +880,10 @@ bool ECMACryptFile::DecryptOfficeFile(const std::wstring &file_name_inp, const s else { cryptData.bAgile = false; - bool fCryptoAPI = GETBIT(nEncryptionInfoFlags, 1); - bool fDocProps = GETBIT(nEncryptionInfoFlags, 2); - bool fExternal = GETBIT(nEncryptionInfoFlags, 3); - bool fAES = GETBIT(nEncryptionInfoFlags, 4); + bool fCryptoAPI = GETBIT(nEncryptionInfoFlags, 2); + bool fDocProps = GETBIT(nEncryptionInfoFlags, 3); + bool fExternal = GETBIT(nEncryptionInfoFlags, 4); + bool fAES = GETBIT(nEncryptionInfoFlags, 5); if ((VersionInfoMajor == 0x0003 || VersionInfoMajor == 0x0004) && VersionInfoMinor == 0x0003) //extensible info { @@ -676,28 +905,6 @@ bool ECMACryptFile::DecryptOfficeFile(const std::wstring &file_name_inp, const s delete pStorage; return false; } -//------------------------------------------------------------------------------------------------------------ - //pStream = new POLE::Stream(pStorage, "DataSpaces/DataSpaceMap"); - //if (pStream) - //{ - // delete pStream; - // pStorage->deleteByName("DataSpaces"); - - // //_UINT32 size = 0; - // //_UINT32 count = 0; - // // - // //pStream->read((unsigned char*)&size, 4); - // //pStream->read((unsigned char*)&count, 4); - - // //for (int i = 0 ; i < count; i++) - // //{ - // // _mapEntry m; - // // ReadMapEntry(pStream, m); - - // // mapEntries.push_back(m); - // //} - // //delete pStream; - //} //------------------------------------------------------------------------------------------------------------ ECMADecryptor decryptor; diff --git a/X2tConverter/test/win32Test/X2tTest.vcproj b/X2tConverter/test/win32Test/X2tTest.vcproj index b1af71bc7f..80962f724d 100644 --- a/X2tConverter/test/win32Test/X2tTest.vcproj +++ b/X2tConverter/test/win32Test/X2tTest.vcproj @@ -364,6 +364,14 @@ RelativePath="..\..\..\XlsxSerializerCom\Writer\BinaryCommonReader.h" > + + + + @@ -627,14 +635,6 @@ - - - -