From 19e3e5897fe56d7727cd725e90cbd0647f606b12 Mon Sep 17 00:00:00 2001 From: ElenaSubbotina Date: Mon, 18 Jul 2016 17:48:43 +0300 Subject: [PATCH] ECMACryptReader --- .../DocFormatLib/Win32/DocFormatLib.vcproj | 2 +- .../source/XlsFormat/Crypt/Decryptor.h | 8 +- OfficeCryptReader/source/ECMACryptReader.cpp | 262 ++++++++++++++++++ OfficeCryptReader/source/ECMACryptReader.h | 81 ++++++ .../win32/ECMACryptReader.vcproj | 163 +++++++++++ OfficeCryptTransform/CryptTransform.cpp | 34 +++ OfficeCryptTransform/CryptTransform.h | 69 +++++ X2tConverter/src/ASCConverters.cpp | 4 +- X2tConverter/src/main.cpp | 10 +- 9 files changed, 624 insertions(+), 9 deletions(-) create mode 100644 OfficeCryptReader/source/ECMACryptReader.cpp create mode 100644 OfficeCryptReader/source/ECMACryptReader.h create mode 100644 OfficeCryptReader/win32/ECMACryptReader.vcproj create mode 100644 OfficeCryptTransform/CryptTransform.cpp create mode 100644 OfficeCryptTransform/CryptTransform.h diff --git a/ASCOfficeDocFile/DocFormatLib/Win32/DocFormatLib.vcproj b/ASCOfficeDocFile/DocFormatLib/Win32/DocFormatLib.vcproj index 6cc5fba585..ee223cab33 100644 --- a/ASCOfficeDocFile/DocFormatLib/Win32/DocFormatLib.vcproj +++ b/ASCOfficeDocFile/DocFormatLib/Win32/DocFormatLib.vcproj @@ -337,7 +337,7 @@ DecryptorPtr; diff --git a/OfficeCryptReader/source/ECMACryptReader.cpp b/OfficeCryptReader/source/ECMACryptReader.cpp new file mode 100644 index 0000000000..2c412b4c77 --- /dev/null +++ b/OfficeCryptReader/source/ECMACryptReader.cpp @@ -0,0 +1,262 @@ +/* + * (c) Copyright Ascensio System SIA 2010-2016 + * + * 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 "../../Common/3dParty/pole/pole.h" +#include "../../Common/DocxFormat/Source/Base/Types_32.h" +#include "../../DesktopEditor/xml/include/xmlutils.h" + +#include "../../OfficeCryptTransform/CryptTransform.h" + +#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 ((wchar_t*)Data, length); + + return res; + +} +void ReadMapEntry(POLE::Stream *pStream, CryptReader::_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++) + { + CryptReader::_refComponent r; + pStream->read((unsigned char*)&r.type, 4); + + r.ref = ReadUnicodeLP(pStream); + m.refComponents.push_back(r); + } + m.dataSpaceName= ReadUnicodeLP(pStream); +} +//-------------------------------------------------------------- +bool CryptReader::DecryptFile(std::wstring file_name, std::wstring folder_out, std::wstring password) +{ + POLE::Storage *pStorage = new POLE::Storage(file_name.c_str()); + + if (!pStorage)return false; + + if (!pStorage->open()) + { + delete pStorage; + return false; + } + + POLE::Stream *pStream = new POLE::Stream(pStorage, "EncryptionInfo"); + if (pStream) + { + _UINT32 nEncryptionInfoSize = 0; + int sz = pStream->read((unsigned char*)&nEncryptionInfoSize, 4); //size uncrypt ?? + + _UINT32 nEncryptionInfoSize1 = 0; + sz = pStream->read((unsigned char*)&nEncryptionInfoSize1, 4); //??? (64) + + unsigned char* byteEncryptionInfo = new unsigned char[nEncryptionInfoSize]; + if (!byteEncryptionInfo) + { + delete pStream; + delete pStorage; + return false; + } + sz = pStream->read(byteEncryptionInfo, nEncryptionInfoSize); + + std::string xml_string((char*) byteEncryptionInfo, sz); + delete []byteEncryptionInfo; + delete pStream; + + if (!ReadEncryptionInfo(xml_string)) + { + delete pStorage; + return false; + } + } + Decryptor decryptor(1); + + decryptor.SetCryptData(keyData.saltValue, keyData.encryptedVerifierHashInput, keyData.encryptedVerifierHashValue); + + if (!decryptor.SetPassword(password)) + { + 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; + //} + + bool result = false; + + pStream = new POLE::Stream(pStorage, "EncryptionPackage"); + if (pStream) + { + _UINT64 length; + pStream->read((unsigned char*)&length, 8); + + while (true) + { + } + + delete pStream; + } +//------------------------------------------------------------------- + + + delete pStorage; + + return result; +} + +bool CryptReader::ReadEncryptionInfo(std::string & xml_string) +{ + XmlUtils1::CXmlLiteReader xmlReader; + + if (!xmlReader.FromStringA(xml_string)) + return false; + + if ( !xmlReader.ReadNextNode() ) + return false; + + 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 ) + { + + } + else if (L"keyEncryptors" == sName) + { + while( xmlReader.ReadNextSiblingNode( nCurDepth + 1 ) ) + { + if (L"keyEncryptor" == 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); + } + } + } + return true; + } +} + diff --git a/OfficeCryptReader/source/ECMACryptReader.h b/OfficeCryptReader/source/ECMACryptReader.h new file mode 100644 index 0000000000..5411771fdf --- /dev/null +++ b/OfficeCryptReader/source/ECMACryptReader.h @@ -0,0 +1,81 @@ +/* + * (c) Copyright Ascensio System SIA 2010-2016 + * + * 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 CryptReader +{ +public: + + void DecryptFile(std::wstring file_name, std::wstring folder_out, std::wstring password); + + 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 _refComponent + //{ + // int type; + // std::wstring ref; + //}; + //struct _mapEntry + //{ + // std::vector<_refComponent> refComponents; + // std::wstring dataSpaceName; + //}; +private: + + bool ReadEncryptionInfo(std::string & xmlString); + + //std::vector<_mapEntry> mapEntries; +//-------------------------------------------------------------- + _keyEncryptor keyData; + std::string encryptedHmacKey; + std::string encryptedHmacValue; + std::vector<_keyEncryptor> keyEncryptors; + +}; diff --git a/OfficeCryptReader/win32/ECMACryptReader.vcproj b/OfficeCryptReader/win32/ECMACryptReader.vcproj new file mode 100644 index 0000000000..fed7902f7e --- /dev/null +++ b/OfficeCryptReader/win32/ECMACryptReader.vcproj @@ -0,0 +1,163 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/OfficeCryptTransform/CryptTransform.cpp b/OfficeCryptTransform/CryptTransform.cpp new file mode 100644 index 0000000000..c826efca45 --- /dev/null +++ b/OfficeCryptTransform/CryptTransform.cpp @@ -0,0 +1,34 @@ +/* + * (c) Copyright Ascensio System SIA 2010-2016 + * + * 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 "CryptTransform.h" + diff --git a/OfficeCryptTransform/CryptTransform.h b/OfficeCryptTransform/CryptTransform.h new file mode 100644 index 0000000000..cc7850dad3 --- /dev/null +++ b/OfficeCryptTransform/CryptTransform.h @@ -0,0 +1,69 @@ +/* + * (c) Copyright Ascensio System SIA 2010-2016 + * + * 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 Decryptor +{ +public: + Decryptor(int type); + virtual ~Decryptor(); + + void Decrypt(void* data, int size); + + bool IsVerify(); + + bool SetPassword(std::wstring password); + + void SetCryptData(std::string salt, std::string verifier, verifier_hash); + +private: + + void *impl_; +}; +// +//class Encryptor +//{ +//public: +// Encryptor(int type); +// virtual ~Encryptor(); +// +// void Encrypt(char* data, int size); +// +// bool SetPassword(std::wstring password); +// +//private: +// +// void *impl_; +//}; \ No newline at end of file diff --git a/X2tConverter/src/ASCConverters.cpp b/X2tConverter/src/ASCConverters.cpp index 43ce9947de..13736628ee 100644 --- a/X2tConverter/src/ASCConverters.cpp +++ b/X2tConverter/src/ASCConverters.cpp @@ -58,6 +58,7 @@ #include "../../HtmlRenderer/include/HTMLRenderer3.h" #include "../../HtmlFile/HtmlFile.h" #include "../../ASCOfficeXlsFile2/source/XlsXlsxConverter/ConvertXls2Xlsx.h" +#include "../../OfficeCryptReader/source/ECMACryptReader.h" #include #include @@ -1265,7 +1266,8 @@ namespace NExtractTools std::wstring sResultDecryptDir = sTemp + FILE_SEPARATOR_STR + _T("crypt_unpacked"); FileSystem::Directory::CreateDirectory(sResultDecryptDir); - + CryptReader cryptReader; + cryptReader.DecryptFile(sFrom, sResultDecryptDir, *params.m_sPassword); //convert from format (detect before) to temp binary folder diff --git a/X2tConverter/src/main.cpp b/X2tConverter/src/main.cpp index e6abe9e894..f98fbf0be4 100644 --- a/X2tConverter/src/main.cpp +++ b/X2tConverter/src/main.cpp @@ -141,8 +141,10 @@ int main(int argc, char *argv[]) if (argc >= 5) sArg4 = CA2T(argv [4]); if (argc >= 6) sArg5 = CA2T(argv [5]); #endif - oInputParams.m_sFileFrom = new std::wstring(sArg1); - oInputParams.m_sFileTo = new std::wstring(sArg2); + oInputParams.m_sFileFrom = new std::wstring(sArg1); + oInputParams.m_sFileTo = new std::wstring(sArg2); + oInputParams.m_sPassword = new std::wstring(L"password"); + // get conversion direction from 3rd argument if (argc > 3) { @@ -163,11 +165,13 @@ int main(int argc, char *argv[]) conversion = TCD_AUTO; } } + sPassword = *oInputParams.m_sPassword; } std::wstring sFileFrom = *oInputParams.m_sFileFrom; std::wstring sFileTo = *oInputParams.m_sFileTo; - int nFormatFrom = AVS_OFFICESTUDIO_FILE_UNKNOWN; + + int nFormatFrom = AVS_OFFICESTUDIO_FILE_UNKNOWN; if(NULL != oInputParams.m_nFormatFrom) nFormatFrom = *oInputParams.m_nFormatFrom; int nFormatTo = AVS_OFFICESTUDIO_FILE_UNKNOWN;