mirror of
https://github.com/ONLYOFFICE/core.git
synced 2026-02-10 18:05:41 +08:00
OdfFormatReader - decrypt
This commit is contained in:
@ -148,8 +148,8 @@ odf_document::Impl::Impl(xml::sax * Reader, const std::wstring & tempPath):
|
||||
}
|
||||
}
|
||||
|
||||
odf_document::Impl::Impl(const std::wstring & srcPath, const std::wstring & tempPath, const std::wstring & Password, const ProgressCallback* CallBack) :
|
||||
context_(new odf_read_context()), pCallBack(CallBack), bUserStopConvert (0), bError(false)
|
||||
odf_document::Impl::Impl(const std::wstring & srcPath, const std::wstring & tempPath, const std::wstring & password, const ProgressCallback* callBack) :
|
||||
context_(new odf_read_context()), pCallBack(callBack), bUserStopConvert (0), bError(false)
|
||||
{
|
||||
office_mime_type_ = 0;
|
||||
|
||||
@ -178,12 +178,12 @@ odf_document::Impl::Impl(const std::wstring & srcPath, const std::wstring & temp
|
||||
|
||||
if (false == map_encryptions_.empty())
|
||||
{
|
||||
if (Password.empty()) return;
|
||||
if (password.empty()) return;
|
||||
|
||||
//decrypt files
|
||||
tmp_folder_ = NSDirectory::CreateDirectoryWithUniqueName(tempPath);
|
||||
|
||||
bError = !decrypt_folder(base_folder_, tmp_folder_);
|
||||
bError = !decrypt_folder(password, base_folder_, tmp_folder_);
|
||||
|
||||
if (bError)
|
||||
return;
|
||||
@ -248,7 +248,7 @@ odf_document::Impl::~Impl()
|
||||
NSDirectory::DeleteDirectory(tmp_folder_);
|
||||
}
|
||||
|
||||
bool odf_document::Impl::decrypt_folder (const std::wstring & srcPath, const std::wstring & dstPath)
|
||||
bool odf_document::Impl::decrypt_folder (const std::wstring &password, const std::wstring & srcPath, const std::wstring & dstPath)
|
||||
{
|
||||
std::vector<std::wstring> arFiles = NSDirectory::GetFiles(srcPath, false);
|
||||
std::vector<std::wstring> arDirectories = NSDirectory::GetDirectories(srcPath);
|
||||
@ -261,7 +261,7 @@ bool odf_document::Impl::decrypt_folder (const std::wstring & srcPath, const std
|
||||
std::map<std::wstring, std::pair<office_element_ptr, int>>::iterator pFind = map_encryptions_.find(arFiles[i]);
|
||||
if ( pFind != map_encryptions_.end() )
|
||||
{
|
||||
result = decrypt_file(arFiles[i], dstPath + FILE_SEPARATOR_STR + sFileName, pFind->second.first, pFind->second.second);
|
||||
result = decrypt_file(password, arFiles[i], dstPath + FILE_SEPARATOR_STR + sFileName, pFind->second.first, pFind->second.second);
|
||||
|
||||
if (false == result)
|
||||
break;
|
||||
@ -277,7 +277,7 @@ bool odf_document::Impl::decrypt_folder (const std::wstring & srcPath, const std
|
||||
|
||||
NSDirectory::CreateDirectory(dstPath + FILE_SEPARATOR_STR + sDirName);
|
||||
|
||||
result = decrypt_folder(arDirectories[i], dstPath + FILE_SEPARATOR_STR + sDirName);
|
||||
result = decrypt_folder(password, arDirectories[i], dstPath + FILE_SEPARATOR_STR + sDirName);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -297,7 +297,7 @@ std::string DecodeBase64(const std::wstring & value1)
|
||||
}
|
||||
return result;
|
||||
}
|
||||
bool odf_document::Impl::decrypt_file (const std::wstring & srcPath, const std::wstring & dstPath, office_element_ptr element, int file_size )
|
||||
bool odf_document::Impl::decrypt_file (const std::wstring &password, const std::wstring & srcPath, const std::wstring & dstPath, office_element_ptr element, int file_size )
|
||||
{
|
||||
manifest_encryption_data* encryption_data = dynamic_cast<manifest_encryption_data*>(element.get());
|
||||
if (!encryption_data) return false;
|
||||
@ -312,29 +312,24 @@ bool odf_document::Impl::decrypt_file (const std::wstring & srcPath, const std::
|
||||
if (key_derivation)
|
||||
{
|
||||
cryptData.saltValue = DecodeBase64(key_derivation->salt_);
|
||||
cryptData.saltSize = cryptData.saltValue.length();
|
||||
cryptData.spinCount = key_derivation->iteration_count_;
|
||||
cryptData.keySize = key_derivation->key_size_;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------
|
||||
if (start_key_generation)
|
||||
{
|
||||
cryptData.start_hashAlgorithm = CRYPT_METHOD::SHA1;
|
||||
cryptData.start_hashSize = 0x14; //128 bit
|
||||
|
||||
if (std::wstring::npos != start_key_generation->start_key_generation_name_.find(L"sha"))
|
||||
{
|
||||
if (std::wstring::npos != start_key_generation->start_key_generation_name_.find(L"512"))
|
||||
{
|
||||
cryptData.start_hashAlgorithm = CRYPT_METHOD::SHA512;
|
||||
cryptData.start_hashSize = 0x40; //320 bit
|
||||
}
|
||||
if (std::wstring::npos != start_key_generation->start_key_generation_name_.find(L"256"))
|
||||
{
|
||||
cryptData.start_hashAlgorithm = CRYPT_METHOD::SHA256;
|
||||
cryptData.start_hashSize = 0x20; //320 bit
|
||||
}
|
||||
}
|
||||
cryptData.start_hashSize = start_key_generation->key_size_;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------
|
||||
if (algorithm)
|
||||
@ -401,20 +396,14 @@ bool odf_document::Impl::decrypt_file (const std::wstring & srcPath, const std::
|
||||
|
||||
file_inp.ReadFile(data, lengthRead, dwSizeRead);
|
||||
|
||||
cryptData.checksum_input = std::string((char*)data, cryptData.checksum_size) ;
|
||||
//------------------------------------------------------------------------------------------
|
||||
|
||||
decryptor.SetCryptData(cryptData);
|
||||
|
||||
if (!decryptor.SetPassword(L"password"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------
|
||||
decryptor.Decrypt(data, dwSizeRead, data_out, file_size);
|
||||
bool result = decryptor.Decrypt(password, data, dwSizeRead, data_out, file_size);
|
||||
delete []data;
|
||||
//------------------------------------------------------------------------------------------------------------
|
||||
|
||||
if (data_out)
|
||||
if (result && data_out)
|
||||
{
|
||||
NSFile::CFileBinary file_out;
|
||||
file_out.CreateFileW(dstPath);
|
||||
@ -422,10 +411,10 @@ bool odf_document::Impl::decrypt_file (const std::wstring & srcPath, const std::
|
||||
file_out.CloseFile();
|
||||
|
||||
delete []data_out;
|
||||
return true;
|
||||
return result;
|
||||
}
|
||||
|
||||
return false;
|
||||
return result;
|
||||
}
|
||||
const std::wstring & odf_document::Impl::get_temp_folder() const
|
||||
{
|
||||
|
||||
@ -97,8 +97,8 @@ private:
|
||||
void parse_manifests(office_element *element);
|
||||
void parse_settings (office_element *element);
|
||||
|
||||
bool decrypt_folder (const std::wstring & srcPath, const std::wstring & dstPath);
|
||||
bool decrypt_file (const std::wstring & srcPath, const std::wstring & dstPath, office_element_ptr data, int size );
|
||||
bool decrypt_folder (const std::wstring &password, const std::wstring & srcPath, const std::wstring & dstPath);
|
||||
bool decrypt_file (const std::wstring &password, const std::wstring & srcPath, const std::wstring & dstPath, office_element_ptr data, int size );
|
||||
|
||||
content_xml_t_ptr content_xml_;
|
||||
content_xml_t_ptr styles_xml_;
|
||||
|
||||
@ -207,7 +207,7 @@ void manifest_key_derivation::add_attributes( const xml::attributes_wc_ptr & Att
|
||||
{
|
||||
CP_APPLY_ATTR(L"manifest:key-derivation-name", key_derivation_name_, std::wstring(L""));
|
||||
CP_APPLY_ATTR(L"manifest:key-size", key_size_, 16);
|
||||
CP_APPLY_ATTR(L"manifest:iteration-count", iteration_count_, 100000);
|
||||
CP_APPLY_ATTR(L"manifest:iteration-count", iteration_count_, 1024);
|
||||
CP_APPLY_ATTR(L"manifest:salt", salt_, std::wstring(L""));
|
||||
|
||||
size_t nFind = key_derivation_name_.find(L"#");
|
||||
|
||||
@ -47,12 +47,12 @@
|
||||
#include "../../Common/3dParty/cryptopp/osrng.h"
|
||||
#include "../../Common/3dParty/cryptopp/hex.h"
|
||||
#include "../../Common/3dParty/cryptopp/blowfish.h"
|
||||
#include "../../Common/3dParty/cryptopp/zinflate.h"
|
||||
|
||||
#include "../../Common/DocxFormat/Source/Base/unicode_util.h"
|
||||
#include "../../Common/DocxFormat/Source/Base/Types_32.h"
|
||||
|
||||
#include "../../DesktopEditor/common/File.h"
|
||||
#include "../../OfficeUtils/src/OfficeUtils.h"
|
||||
|
||||
static const unsigned char encrVerifierHashInputBlockKey[8] = { 0xfe, 0xa7, 0xd2, 0x76, 0x3b, 0x4b, 0x9e, 0x79 };
|
||||
static const unsigned char encrVerifierHashValueBlockKey[8] = { 0xd7, 0xaa, 0x0f, 0x6d, 0x30, 0x61, 0x34, 0x4e };
|
||||
@ -939,65 +939,16 @@ ODFDecryptor::~ODFDecryptor()
|
||||
{
|
||||
}
|
||||
|
||||
bool ODFDecryptor::SetPassword(std::wstring _password)
|
||||
{
|
||||
bVerify = false;
|
||||
|
||||
wpassword = _password;
|
||||
password = NSFile::CUtf8Converter::GetUtf8StringFromUnicode(_password);
|
||||
|
||||
if (password.empty()) return false;
|
||||
|
||||
_buf empty (NULL, 0, false);
|
||||
_buf pInput (cryptData.checksum_input);
|
||||
_buf pChecksum (cryptData.checksum);
|
||||
_buf pOutput (pInput.size);
|
||||
|
||||
Decrypt(pInput.ptr, pInput.size, pOutput.ptr, cryptData.checksum_size);
|
||||
|
||||
_buf pOutputHash = HashAppend(pOutput, empty, cryptData.checksum_hashAlgorithm);
|
||||
|
||||
bVerify = (pChecksum == pOutputHash);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ODFDecryptor::IsVerify()
|
||||
{
|
||||
return bVerify;
|
||||
}
|
||||
|
||||
void ODFDecryptor::SetCryptData(_odfCryptData & data)
|
||||
{
|
||||
cryptData = data;
|
||||
}
|
||||
void ODFDecryptor::Decrypt(char* data, const size_t size, const unsigned long start_iv_block)
|
||||
{//without deflate
|
||||
//if (!bVerify) return;
|
||||
|
||||
_buf pPassword (wpassword);
|
||||
_buf pSalt (cryptData.saltValue);
|
||||
_buf ivi (cryptData.initializationVector);
|
||||
_buf empty (NULL, 0, false);
|
||||
|
||||
_buf pKey = GenerateOdfKey(pSalt, pPassword, cryptData.keySize, cryptData.spinCount, cryptData.start_hashAlgorithm);
|
||||
|
||||
_buf pInp((unsigned char*)data, size, false);
|
||||
_buf pOut(size);
|
||||
|
||||
DecryptCipher(pKey, ivi, pInp, pOut, cryptData.cipherAlgorithm);
|
||||
|
||||
memcpy(data, pOut.ptr, size);
|
||||
}
|
||||
|
||||
void ODFDecryptor::Decrypt(unsigned char* data_inp, int size_inp, unsigned char*& data_out, int &size_out)
|
||||
bool ODFDecryptor::Decrypt(const std::wstring &wpassword, unsigned char* data_inp, int size_inp, unsigned char*& data_out, int &size_out)
|
||||
{
|
||||
//if (!bVerify)
|
||||
//{
|
||||
// size_out = 0;
|
||||
// return;
|
||||
//}
|
||||
if (size_out < 1) size_out = size_inp;
|
||||
bVerify = false;
|
||||
|
||||
std::string password = NSFile::CUtf8Converter::GetUtf8StringFromUnicode(wpassword);
|
||||
|
||||
_buf pPassword (password);
|
||||
_buf pSalt (cryptData.saltValue);
|
||||
@ -1009,18 +960,32 @@ void ODFDecryptor::Decrypt(unsigned char* data_inp, int size_inp, unsigned char*
|
||||
_buf pInp(data_inp, size_inp, false);
|
||||
_buf pOut(size_inp);
|
||||
|
||||
DecryptCipher(pKey, ivi, pInp, pOut, cryptData.cipherAlgorithm);
|
||||
if (false == DecryptCipher(pKey, ivi, pInp, pOut, cryptData.cipherAlgorithm))
|
||||
return false;
|
||||
|
||||
data_out = new unsigned char[size_out];
|
||||
try
|
||||
{
|
||||
data_out = new unsigned char[size_out];
|
||||
|
||||
Inflator inflator(new ArraySink( data_out, size_out));
|
||||
|
||||
inflator.Put(pOut.ptr, pOut.size);
|
||||
inflator.MessageEnd();
|
||||
|
||||
CInflate inflate;
|
||||
inflate.SetOut(data_out, size_out);
|
||||
inflate.SetIn(pOut.ptr, pOut.size);
|
||||
|
||||
inflate.Init2();
|
||||
|
||||
int nRes = inflate.Process(DEFLATE_FINISH);
|
||||
inflate.End();
|
||||
bVerify = true;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
//_buf pChecksum (cryptData.checksum);
|
||||
//_buf pOutputLimit (data_out, cryptData.checksum_size, false);
|
||||
|
||||
//_buf pOutputHash = HashAppend(pOutputLimit, empty, cryptData.checksum_hashAlgorithm);
|
||||
|
||||
//bVerify = (pChecksum == pOutputHash);
|
||||
|
||||
return bVerify;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -110,19 +110,18 @@ struct _odfCryptData
|
||||
{
|
||||
CRYPT_METHOD::_cipherAlgorithm cipherAlgorithm = CRYPT_METHOD::AES_CBC;
|
||||
|
||||
CRYPT_METHOD::_hashAlgorithm start_hashAlgorithm = CRYPT_METHOD::SHA256;
|
||||
int start_hashSize = 0x20;
|
||||
CRYPT_METHOD::_hashAlgorithm start_hashAlgorithm = CRYPT_METHOD::SHA1;
|
||||
int start_hashSize = 20;
|
||||
|
||||
int spinCount = 1024;
|
||||
int keySize = 16;
|
||||
|
||||
int spinCount = 100000;
|
||||
int keySize = 0x20;
|
||||
int saltSize = 0x10;
|
||||
std::string saltValue;
|
||||
std::string initializationVector;
|
||||
|
||||
std::string checksum_input;
|
||||
std::string checksum;
|
||||
int checksum_size = 1024;
|
||||
CRYPT_METHOD::_hashAlgorithm checksum_hashAlgorithm = CRYPT_METHOD::SHA256;
|
||||
CRYPT_METHOD::_hashAlgorithm checksum_hashAlgorithm = CRYPT_METHOD::SHA1;
|
||||
};
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
class ECMAEncryptor
|
||||
@ -172,29 +171,17 @@ private:
|
||||
bool bVerify;
|
||||
};
|
||||
|
||||
class ODFDecryptor : public Decryptor
|
||||
class ODFDecryptor
|
||||
{
|
||||
public:
|
||||
ODFDecryptor();
|
||||
virtual ~ODFDecryptor();
|
||||
|
||||
virtual void Init(const unsigned long val) {}
|
||||
|
||||
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);
|
||||
//without deflate
|
||||
|
||||
virtual bool SetPassword (std::wstring password);
|
||||
virtual bool IsVerify();
|
||||
|
||||
void SetCryptData(_odfCryptData &data);
|
||||
|
||||
void Decrypt (unsigned char* data_inp, int size_inp, unsigned char*& data_out, int &size_out);
|
||||
bool Decrypt (const std::wstring &wpassword, unsigned char* data_inp, int size_inp, unsigned char*& data_out, int &size_out);
|
||||
|
||||
private:
|
||||
|
||||
std::wstring wpassword;
|
||||
std::string password; //utf8
|
||||
_odfCryptData cryptData;
|
||||
bool bVerify;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user