From 7977bcf069227f7dff0b08b5949d5720c4f8ea49 Mon Sep 17 00:00:00 2001 From: ElenaSubbotina Date: Wed, 29 Mar 2017 12:47:58 +0300 Subject: [PATCH] . --- .../DocDocxConverter/EncryptionHeader.h | 6 +- OfficeCryptReader/source/ECMACryptReader.cpp | 506 ------------------ OfficeCryptReader/source/ECMACryptReader.h | 53 -- 3 files changed, 3 insertions(+), 562 deletions(-) delete mode 100644 OfficeCryptReader/source/ECMACryptReader.cpp delete mode 100644 OfficeCryptReader/source/ECMACryptReader.h diff --git a/ASCOfficeDocFile/DocDocxConverter/EncryptionHeader.h b/ASCOfficeDocFile/DocDocxConverter/EncryptionHeader.h index 660da53d31..63766a64ab 100644 --- a/ASCOfficeDocFile/DocDocxConverter/EncryptionHeader.h +++ b/ASCOfficeDocFile/DocDocxConverter/EncryptionHeader.h @@ -50,8 +50,8 @@ namespace DocFileFormat EncryptionHeader( FileInformationBlock* fib, POLE::Stream* tableStream ); private: - CRYPT::CryptRC4Data crypt_data_rc4; - CRYPT::ECMADecryptor::_cryptData crypt_data_aes; - bool bStandard; + CRYPT::_rc4CryptData crypt_data_rc4; + CRYPT::_ecmaCryptData crypt_data_aes; + bool bStandard; }; } diff --git a/OfficeCryptReader/source/ECMACryptReader.cpp b/OfficeCryptReader/source/ECMACryptReader.cpp deleted file mode 100644 index d6cfe59ba4..0000000000 --- a/OfficeCryptReader/source/ECMACryptReader.cpp +++ /dev/null @@ -1,506 +0,0 @@ -/* - * (c) Copyright Ascensio System SIA 2010-2017 - * - * This program is a free software product. You can redistribute it and/or - * modify it under the terms of the GNU Affero General Public License (AGPL) - * version 3 as published by the Free Software Foundation. In accordance with - * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect - * that Ascensio System SIA expressly excludes the warranty of non-infringement - * of any third-party rights. - * - * This program is distributed WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For - * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html - * - * You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, - * EU, LV-1021. - * - * The interactive user interfaces in modified source and object code versions - * of the Program must display Appropriate Legal Notices, as required under - * Section 5 of the GNU AGPL version 3. - * - * Pursuant to Section 7(b) of the License you must retain the original Product - * logo when distributing the program. Pursuant to Section 7(e) we decline to - * grant you any rights under trademark law for use of our trademarks. - * - * All the Product's GUI elements, including illustrations and icon sets, as - * well as technical writing content are licensed under the terms of the - * Creative Commons Attribution-ShareAlike 4.0 International. See the License - * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode - * - */ - -#include "ECMACryptReader.h" -#include "CryptTransform.h" - -#include "../../Common/3dParty/pole/pole.h" -#include "../../Common/DocxFormat/Source/Base/Types_32.h" - -#include "../../DesktopEditor/common/File.h" -#include "../../DesktopEditor/xml/include/xmlutils.h" - -#include "../../ASCOfficeDocFile/DocDocxConverter/MemoryStream.h" - -using namespace CRYPT; - -#define GETBIT(from, num) ((from & (1 << num)) != 0) - -#define WritingElement_ReadAttributes_Start(Reader) \ - if ( Reader.GetAttributesCount() <= 0 )\ - return false;\ - if ( !Reader.MoveToFirstAttribute() )\ - return false;\ - std::string wsName = Reader.GetNameA();\ - while( !wsName.empty() )\ - { - -#define WritingElement_ReadAttributes_Read_if(Reader, AttrName, Value) \ - if ( AttrName == wsName )\ - {\ - Value = Reader.GetTextA();\ - } - -#define WritingElement_ReadAttributes_Read_else_if(Reader, AttrName, Value) \ - else if ( AttrName == wsName )\ - Value = Reader.GetTextA(); - -#define WritingElement_ReadAttributes_ReadSingle(Reader, AttrName, Value) \ - if ( AttrName == wsName )\ - {\ - Value = Reader.GetTextA();\ - break;\ - } - -#define WritingElement_ReadAttributes_End(Reader) \ - if ( !Reader.MoveToNextAttribute() ) \ - break;\ - wsName = Reader.GetNameA();\ - }\ - Reader.MoveToElement(); - -std::wstring ReadUnicodeLP(POLE::Stream *pStream) -{ - if (!pStream) return L""; - - _UINT32 length = 0; - pStream->read((unsigned char*)&length, 4); - - unsigned char* Data = new unsigned char[length * 2]; - pStream->read(Data, length * 2); - - std::wstring res; - - if (sizeof(wchar_t) == 4) - { - unsigned int nLength = length; - - wchar_t* ptr = new wchar_t [length]; - - UTF16* pStrUtf16 = (UTF16*) Data; - UTF32 *pStrUtf32 = (UTF32 *) ptr; - - const UTF16 *pStrUtf16_Conv = pStrUtf16; - UTF32 *pStrUtf32_Conv = pStrUtf32; - - ConversionResult eUnicodeConversionResult = ConvertUTF16toUTF32 (&pStrUtf16_Conv, &pStrUtf16[nLength] - , &pStrUtf32_Conv, &pStrUtf32 [nLength], strictConversion); - - if (conversionOK != eUnicodeConversionResult) - { - } - res = std::wstring(ptr, length); - delete ptr; - } - else - res = std::wstring((wchar_t*)Data, length); - - - return res; - -} - -void ReadMapEntry(POLE::Stream *pStream, ECMACryptReader::_mapEntry & m) -{ - if (!pStream) return; - - _UINT32 length = 0; - pStream->read((unsigned char*)&length, 4); - - _UINT32 refCount = 0; - pStream->read((unsigned char*)&refCount, 4); - - for (int i = 0 ; i < refCount; i++) - { - ECMACryptReader::_refComponent r; - pStream->read((unsigned char*)&r.type, 4); - - r.ref = ReadUnicodeLP(pStream); - m.refComponents.push_back(r); - } - m.dataSpaceName= ReadUnicodeLP(pStream); -} - -std::string DecodeBase64(const std::string & value) -{ - int nLength = 0; - unsigned char *pData = NULL; - std::string result; - - NSFile::CBase64Converter::Decode(value.c_str(), value.length(), pData, nLength); - if (pData) - { - result = std::string((char*)pData, nLength); - delete []pData; pData = NULL; - } - return result; -} -//----------------------------------------------------------------------------------------------------------------------- -struct _keyEncryptor -{ - std::string spinCount; - std::string saltSize; - std::string blockSize; - std::string keyBits; - std::string hashSize; - - std::string cipherAlgorithm; - std::string cipherChaining; - std::string hashAlgorithm; - - std::string saltValue; - std::string encryptedVerifierHashInput; - std::string encryptedVerifierHashValue; - std::string encryptedKeyValue; -}; -struct _dataIntegrity -{ - std::string encryptedHmacKey; - std::string encryptedHmacValue; -}; -bool ReadXmlEncryptionInfo(const std::string & xml_string, ECMADecryptor::_cryptData & cryptData) -{ - XmlUtils::CXmlLiteReader xmlReader; - - if (!xmlReader.FromStringA(xml_string)) - return false; - - if ( !xmlReader.ReadNextNode() ) - return false; - - _dataIntegrity dataIntegrity; - _keyEncryptor keyData; - std::vector<_keyEncryptor> keyEncryptors; - - int nCurDepth = xmlReader.GetDepth(); - while( xmlReader.ReadNextSiblingNode( nCurDepth ) ) - { - std::wstring sName = xmlReader.GetName(); - if ( L"keyData" == sName ) - { - WritingElement_ReadAttributes_Start( xmlReader) - WritingElement_ReadAttributes_Read_if ( xmlReader, "saltSize", keyData.saltSize ) - WritingElement_ReadAttributes_Read_else_if ( xmlReader, "blockSize", keyData.blockSize ) - WritingElement_ReadAttributes_Read_else_if ( xmlReader, "keyBits", keyData.keyBits ) - WritingElement_ReadAttributes_Read_else_if ( xmlReader, "hashSize", keyData.hashSize ) - WritingElement_ReadAttributes_Read_else_if ( xmlReader, "cipherAlgorithm", keyData.cipherAlgorithm ) - WritingElement_ReadAttributes_Read_else_if ( xmlReader, "cipherChaining", keyData.cipherChaining ) - WritingElement_ReadAttributes_Read_else_if ( xmlReader, "hashAlgorithm", keyData.hashAlgorithm ) - WritingElement_ReadAttributes_Read_else_if ( xmlReader, "saltValue", keyData.saltValue ) - WritingElement_ReadAttributes_End( xmlReader ) - } - else if ( L"dataIntegrity" == sName ) - { - WritingElement_ReadAttributes_Start( xmlReader) - WritingElement_ReadAttributes_Read_if ( xmlReader, "encryptedHmacKey", dataIntegrity.encryptedHmacKey) - WritingElement_ReadAttributes_Read_else_if ( xmlReader, "encryptedHmacValue", dataIntegrity.encryptedHmacValue) - WritingElement_ReadAttributes_End( xmlReader ) - } - else if (L"keyEncryptors" == sName) - { - while( xmlReader.ReadNextSiblingNode( nCurDepth + 1 ) ) - { - sName = xmlReader.GetName(); - if (L"keyEncryptor" == sName) - { - while( xmlReader.ReadNextSiblingNode( nCurDepth + 2 ) ) - { - sName = xmlReader.GetName(); - if (L"p:encryptedKey" == sName) - { - _keyEncryptor k={}; - - WritingElement_ReadAttributes_Start( xmlReader) - WritingElement_ReadAttributes_Read_if ( xmlReader, "spinCount", k.spinCount ) - WritingElement_ReadAttributes_Read_else_if( xmlReader, "saltSize", k.saltSize ) - WritingElement_ReadAttributes_Read_else_if( xmlReader, "blockSize", k.blockSize ) - WritingElement_ReadAttributes_Read_else_if( xmlReader, "keyBits", k.keyBits ) - WritingElement_ReadAttributes_Read_else_if( xmlReader, "hashSize", k.hashSize ) - WritingElement_ReadAttributes_Read_else_if( xmlReader, "cipherAlgorithm", k.cipherAlgorithm ) - WritingElement_ReadAttributes_Read_else_if( xmlReader, "cipherChaining", k.cipherChaining ) - WritingElement_ReadAttributes_Read_else_if( xmlReader, "hashAlgorithm", k.hashAlgorithm ) - WritingElement_ReadAttributes_Read_else_if( xmlReader, "saltValue", k.saltValue ) - WritingElement_ReadAttributes_Read_else_if( xmlReader, "encryptedVerifierHashInput", k.encryptedVerifierHashInput ) - WritingElement_ReadAttributes_Read_else_if( xmlReader, "encryptedVerifierHashValue", k.encryptedVerifierHashValue ) - WritingElement_ReadAttributes_Read_else_if( xmlReader, "encryptedKeyValue", k.encryptedKeyValue ) - WritingElement_ReadAttributes_End( xmlReader ) - - keyEncryptors.push_back(k); - } - } - } - } - } - } - - if (keyEncryptors.empty()) return false; - - cryptData.spinCount = atoi(keyEncryptors[0].spinCount.c_str()); - cryptData.blockSize = atoi(keyEncryptors[0].blockSize.c_str()); - cryptData.hashSize = atoi(keyEncryptors[0].hashSize.c_str()); - cryptData.saltSize = atoi(keyEncryptors[0].saltSize.c_str()); - cryptData.keySize = atoi(keyEncryptors[0].keyBits.c_str() ) / 8; - - cryptData.dataSaltValue = DecodeBase64(keyData.saltValue); - cryptData.saltValue = DecodeBase64(keyEncryptors[0].saltValue); - cryptData.encryptedKeyValue = DecodeBase64(keyEncryptors[0].encryptedKeyValue); - cryptData.encryptedVerifierInput = DecodeBase64(keyEncryptors[0].encryptedVerifierHashInput); - cryptData.encryptedVerifierValue = DecodeBase64(keyEncryptors[0].encryptedVerifierHashValue); - - cryptData.encryptedHmacKey = DecodeBase64(dataIntegrity.encryptedHmacKey); - cryptData.encryptedHmacValue = DecodeBase64(dataIntegrity.encryptedHmacValue); - - if (keyData.cipherAlgorithm == "AES") - { - 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; - - return true; -} - -bool ReadStandartEncryptionInfo(unsigned char* data, int size, ECMADecryptor::_cryptData & cryptData) -{ - if (!data || size < 1) return false; - MemoryStream mem_stream(data, size, false); - -//EncryptionHeader - int HeaderSize = mem_stream.ReadUInt32(); - int Flags = mem_stream.ReadUInt32(); - int SizeExtra = mem_stream.ReadUInt32(); - int AlgID = mem_stream.ReadUInt32(); - int AlgIDHash = mem_stream.ReadUInt32(); - int KeySize = mem_stream.ReadUInt32(); - int ProviderType= mem_stream.ReadUInt32(); - int Reserved1 = mem_stream.ReadUInt32(); - int Reserved2 = mem_stream.ReadUInt32(); - - int pos = mem_stream.GetPosition(); - - while(pos < size - 1) - { - if (data[pos] == 0 && data[pos + 1] == 0) - { - break; - } - pos+=2;//unicode null-terminate string - } - int szCSPName = pos - mem_stream.GetPosition() + 2; - - unsigned char* strData = mem_stream.ReadBytes(szCSPName, true); - if (strData) - { - delete []strData; - } -//EncryptionVerifier - cryptData.saltSize = mem_stream.ReadUInt32(); - - cryptData.saltValue = std::string((char*)data + mem_stream.GetPosition(), cryptData.saltSize); - mem_stream.ReadBytes(cryptData.saltSize, false); - - cryptData.encryptedVerifierInput = std::string((char*)data + mem_stream.GetPosition(), 0x10); - mem_stream.ReadBytes(0x10, false); - - cryptData.hashSize = mem_stream.ReadUInt32(); - - int szEncryptedVerifierHash = (ProviderType == 0x0001) ? 0x14 : 0x20; - cryptData.encryptedVerifierValue = std::string((char*)data + mem_stream.GetPosition(), szEncryptedVerifierHash); - mem_stream.ReadBytes(szEncryptedVerifierHash, false); - - pos = mem_stream.GetPosition(); - -//------------------------------------------------------------------------------------------ - cryptData.hashAlgorithm = CRYPT_METHOD::SHA1; //by AlgIDHash -> 0x0000 || 0x8004 - cryptData.spinCount = 50000; - - switch(AlgID) - { - case 0x6801: - cryptData.cipherAlgorithm = CRYPT_METHOD::RC4; - cryptData.keySize = KeySize / 8; - break; - case 0x660E: - cryptData.cipherAlgorithm = CRYPT_METHOD::AES_ECB; - cryptData.keySize = 128 /8; - break; - case 0x660F: - cryptData.cipherAlgorithm = CRYPT_METHOD::AES_ECB; - cryptData.keySize = 192 /8; - break; - case 0x6610: - cryptData.cipherAlgorithm = CRYPT_METHOD::AES_ECB; - cryptData.keySize = 256 /8; - break; - } - return true; -} - -bool ReadExtensibleEncryptionInfo(unsigned char* data, int size, ECMADecryptor::_cryptData & cryptData) -{ - return false; -} - - -//-------------------------------------------------------------- - -bool ECMACryptReader::DecryptOfficeFile(std::wstring file_name_inp, std::wstring file_name_out, std::wstring password) -{ - POLE::Storage *pStorage = new POLE::Storage(file_name_inp.c_str()); - - if (!pStorage)return false; - - if (!pStorage->open()) - { - delete pStorage; - return false; - } - ECMADecryptor::_cryptData cryptData; - bool result = false; - - POLE::Stream *pStream = new POLE::Stream(pStorage, "EncryptionInfo"); - if (pStream) - { - _UINT16 VersionInfoMajor = 0, VersionInfoMinor = 0; - - pStream->read((unsigned char*)&VersionInfoMajor, 2); - pStream->read((unsigned char*)&VersionInfoMinor, 2); - - _UINT32 nEncryptionInfoFlags = 0; - pStream->read((unsigned char*)&nEncryptionInfoFlags, 4); - - int nEncryptionInfoSize = pStream->size() - 8; - unsigned char* byteEncryptionInfo = new unsigned char[nEncryptionInfoSize]; - if (!byteEncryptionInfo) - { - delete pStream; - delete pStorage; - return false; - } - nEncryptionInfoSize = pStream->read(byteEncryptionInfo, nEncryptionInfoSize); - delete pStream; - - if (VersionInfoMajor == 0x0004 && VersionInfoMinor == 0x0004) - {//agile info - std::string xml_string((char*) byteEncryptionInfo, nEncryptionInfoSize); - delete []byteEncryptionInfo; - - cryptData.bAgile = true; - result = ReadXmlEncryptionInfo(xml_string, cryptData); - } - else - { - cryptData.bAgile = false; - bool fCryptoAPI = GETBIT(nEncryptionInfoFlags, 1); - bool fDocProps = GETBIT(nEncryptionInfoFlags, 2); - bool fExternal = GETBIT(nEncryptionInfoFlags, 3); - bool fAES = GETBIT(nEncryptionInfoFlags, 4); - - if ((VersionInfoMajor == 0x0003 || VersionInfoMajor == 0x0004) && VersionInfoMinor == 0x0003) //extensible info - { - result = ReadExtensibleEncryptionInfo(byteEncryptionInfo, nEncryptionInfoSize, cryptData); - } - else if ((VersionInfoMajor == 0x0003 || VersionInfoMajor == 0x0004) && VersionInfoMinor == 0x0002) //standart info - { - result = ReadStandartEncryptionInfo(byteEncryptionInfo, nEncryptionInfoSize, cryptData); - } - else - { - // look in DocFormat - } - delete []byteEncryptionInfo; - } - } - if (!result) - { - delete pStorage; - return false; - } -//------------------------------------------------------------------------------------------------------------ - //pStream = new POLE::Stream(pStorage, "DataSpaces/DataSpaceMap"); - //if (pStream) - //{ - // _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; - - decryptor.SetCryptData(cryptData); - - if (!decryptor.SetPassword(password)) - { - if (password.empty()) - { - password = L"VelvetSweatshop"; - if (!decryptor.SetPassword(password)) - return false; - } - else - return false; - } -//------------------------------------------------------------------------------------------------------------ - pStream = new POLE::Stream(pStorage, "EncryptedPackage"); - if (pStream->size() > 0) - { - _UINT64 lengthData, lengthRead = pStream->size() - 8; - pStream->read((unsigned char*)&lengthData, 8); - - unsigned char* data = new unsigned char[lengthRead]; - unsigned char* data_out = NULL; - - pStream->read(data, lengthRead); - - decryptor.Decrypt(data, lengthRead, data_out);//todoo сделать покусочное чтение декриптование - delete pStream; - - if (data_out) - { - NSFile::CFileBinary f; - f.CreateFileW(file_name_out); - f.WriteFile(data_out, lengthData); - f.CloseFile(); - - result = true; - } - } -//------------------------------------------------------------------- - delete pStorage; - return result; -} diff --git a/OfficeCryptReader/source/ECMACryptReader.h b/OfficeCryptReader/source/ECMACryptReader.h deleted file mode 100644 index 5ce6374cd4..0000000000 --- a/OfficeCryptReader/source/ECMACryptReader.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * (c) Copyright Ascensio System SIA 2010-2017 - * - * This program is a free software product. You can redistribute it and/or - * modify it under the terms of the GNU Affero General Public License (AGPL) - * version 3 as published by the Free Software Foundation. In accordance with - * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect - * that Ascensio System SIA expressly excludes the warranty of non-infringement - * of any third-party rights. - * - * This program is distributed WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For - * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html - * - * You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, - * EU, LV-1021. - * - * The interactive user interfaces in modified source and object code versions - * of the Program must display Appropriate Legal Notices, as required under - * Section 5 of the GNU AGPL version 3. - * - * Pursuant to Section 7(b) of the License you must retain the original Product - * logo when distributing the program. Pursuant to Section 7(e) we decline to - * grant you any rights under trademark law for use of our trademarks. - * - * All the Product's GUI elements, including illustrations and icon sets, as - * well as technical writing content are licensed under the terms of the - * Creative Commons Attribution-ShareAlike 4.0 International. See the License - * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode - * - */ -#pragma once - -#include -#include - -class ECMACryptReader -{ -public: - bool DecryptOfficeFile(std::wstring file_name_inp, std::wstring file_name_out, std::wstring password); - - struct _refComponent - { - int type; - std::wstring ref; - }; - struct _mapEntry - { - std::vector<_refComponent> refComponents; - std::wstring dataSpaceName; - }; - std::vector<_mapEntry> mapEntries; -};