mirror of
https://github.com/ONLYOFFICE/core.git
synced 2026-07-19 23:02:34 +08:00
PdfReader - decrypt files revision 6(fix bug #17002)
This commit is contained in:
@ -62,10 +62,8 @@
|
||||
#pragma comment(lib, "../../build/bin/icu/win_32/icuuc.lib")
|
||||
#endif
|
||||
|
||||
HRESULT convert_single(PdfReader::CPdfReader& oReader, std::wstring srcFileName)
|
||||
HRESULT convert_single(PdfReader::CPdfReader& oReader, const std::wstring & srcFileName, const std::wstring & sPassword)
|
||||
{
|
||||
std::wstring sPassword = L"58455fdc2013";
|
||||
|
||||
if (oReader.LoadFromFile(srcFileName.c_str(), L"", sPassword, sPassword))
|
||||
{
|
||||
int nPagesCount = oReader.GetPagesCount();
|
||||
@ -99,7 +97,7 @@ HRESULT convert_single(PdfReader::CPdfReader& oReader, std::wstring srcFileName)
|
||||
|
||||
return S_FALSE;
|
||||
}
|
||||
HRESULT convert_directory(PdfReader::CPdfReader& oReader, std::wstring pathName)
|
||||
HRESULT convert_directory(PdfReader::CPdfReader& oReader, std::wstring pathName, const std::wstring & sPassword)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
@ -107,7 +105,7 @@ HRESULT convert_directory(PdfReader::CPdfReader& oReader, std::wstring pathName)
|
||||
|
||||
for (size_t i = 0; i < arFiles.size(); i++)
|
||||
{
|
||||
hr = convert_single(oReader, arFiles[i]);
|
||||
hr = convert_single(oReader, arFiles[i], sPassword);
|
||||
|
||||
printf("%d of %d %S \tresult = %d\n", i + 1, arFiles.size(), arFiles[i].c_str(), hr);
|
||||
|
||||
@ -124,14 +122,17 @@ int _tmain(int argc, _TCHAR* argv[])
|
||||
|
||||
PdfReader::CPdfReader oPdfReader(pApplicationFonts);
|
||||
|
||||
HRESULT hr = -1;
|
||||
HRESULT hr = S_FALSE;
|
||||
|
||||
std::wstring sPassword = argc > 2 ? argv[2] : L"";
|
||||
|
||||
if (NSFile::CFileBinary::Exists(argv[1]))
|
||||
{
|
||||
hr = convert_single(oPdfReader, argv[1]);
|
||||
hr = convert_single(oPdfReader, argv[1], sPassword);
|
||||
}
|
||||
else if (NSDirectory::Exists(argv[1]))
|
||||
{
|
||||
hr = convert_directory(oPdfReader, argv[1]);
|
||||
hr = convert_directory(oPdfReader, argv[1], sPassword);
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
@ -57,17 +57,46 @@ namespace PdfReader
|
||||
memcpy(sDigest, buffer.BytePtr(), buffer.SizeInBytes());
|
||||
return;
|
||||
}
|
||||
static void SHA256(unsigned char *sMessage, int nMessageLen, unsigned char *sDigest)
|
||||
static int SHA(int type, unsigned char *sMessage, int nMessageLen, unsigned char *sDigest)
|
||||
{
|
||||
CryptoPP::SHA256 hash;
|
||||
|
||||
hash.Update( sMessage, nMessageLen);
|
||||
int res = 0;
|
||||
switch(type)
|
||||
{
|
||||
case 0:
|
||||
case 256:
|
||||
{
|
||||
CryptoPP::SHA256 hash;
|
||||
hash.Update( sMessage, nMessageLen > 0 ? nMessageLen : hash.DigestSize());
|
||||
|
||||
CryptoPP::SecByteBlock buffer(hash.DigestSize());
|
||||
hash.Final(buffer);
|
||||
CryptoPP::SecByteBlock buffer(res = hash.DigestSize());
|
||||
hash.Final(buffer);
|
||||
|
||||
memcpy(sDigest, buffer.BytePtr(), buffer.SizeInBytes());
|
||||
return;
|
||||
memcpy(sDigest, buffer.BytePtr(), buffer.SizeInBytes());
|
||||
}break;
|
||||
case 1:
|
||||
case 384:
|
||||
{
|
||||
CryptoPP::SHA384 hash;
|
||||
hash.Update( sMessage, nMessageLen > 0 ? nMessageLen : hash.DigestSize());
|
||||
|
||||
CryptoPP::SecByteBlock buffer(res = hash.DigestSize());
|
||||
hash.Final(buffer);
|
||||
|
||||
memcpy(sDigest, buffer.BytePtr(), buffer.SizeInBytes());
|
||||
}break;
|
||||
case 2:
|
||||
case 512:
|
||||
{
|
||||
CryptoPP::SHA512 hash;
|
||||
hash.Update( sMessage, nMessageLen > 0 ? nMessageLen : hash.DigestSize());
|
||||
|
||||
CryptoPP::SecByteBlock buffer(res = hash.DigestSize());
|
||||
hash.Final(buffer);
|
||||
|
||||
memcpy(sDigest, buffer.BytePtr(), buffer.SizeInBytes());
|
||||
}break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
static unsigned char passwordPad[32] =
|
||||
{
|
||||
@ -150,8 +179,10 @@ namespace PdfReader
|
||||
std::string sUserPassword = NSFile::CUtf8Converter::GetUtf8StringFromUnicode(wsUserPassword);
|
||||
return MakeFileKey2(handler, sUserPassword);
|
||||
}
|
||||
else if ( handler->m_nEncryptRevision == 5 )
|
||||
else
|
||||
{
|
||||
bool bValidate = false;
|
||||
|
||||
NSUnicodeConverter::CUnicodeConverter conv;
|
||||
std::string sUserPassword = conv.SASLprepToUtf8(wsUserPassword);
|
||||
int len = sUserPassword.length() < 127 ? sUserPassword.length() : 127;
|
||||
@ -164,7 +195,12 @@ namespace PdfReader
|
||||
CryptoPP::SecByteBlock buffer(hash.DigestSize());
|
||||
hash.Final(buffer);
|
||||
|
||||
bool bValidate = (0 == memcmp(buffer.BytePtr(), handler->m_seUserKey->GetUBuffer(), 32));
|
||||
if ( handler->m_nEncryptRevision > 5 )
|
||||
{
|
||||
MakeFileKey3(sUserPassword, buffer.BytePtr(), buffer.SizeInBytes());
|
||||
}
|
||||
|
||||
bValidate = (0 == memcmp(buffer.BytePtr(), handler->m_seUserKey->GetUBuffer(), 32));
|
||||
|
||||
if (bValidate)
|
||||
{
|
||||
@ -174,9 +210,14 @@ namespace PdfReader
|
||||
CryptoPP::SecByteBlock buffer(hash.DigestSize());
|
||||
hash.Final(buffer);
|
||||
|
||||
if ( handler->m_nEncryptRevision > 5 )
|
||||
{
|
||||
MakeFileKey3(sUserPassword, buffer.BytePtr(), buffer.SizeInBytes());
|
||||
}
|
||||
|
||||
CryptoPP::AES::Decryption aesDecryption(buffer.BytePtr(), buffer.SizeInBytes());
|
||||
unsigned char* empty[16] = {};
|
||||
CryptoPP::CBC_Mode_ExternalCipher::Decryption cbcDecryption( aesDecryption, (unsigned char*)empty );
|
||||
unsigned char empty[16] = {};
|
||||
CryptoPP::CBC_Mode_ExternalCipher::Decryption cbcDecryption( aesDecryption, empty );
|
||||
|
||||
CryptoPP::StreamTransformationFilter stfDecryptor(cbcDecryption, new CryptoPP::ArraySink( (unsigned char*)handler->m_sFileKey, 32), CryptoPP::StreamTransformationFilter::NO_PADDING );
|
||||
stfDecryptor.Put( handler->m_seUserEncryptionKey->GetUBuffer(), 32);
|
||||
@ -193,6 +234,11 @@ namespace PdfReader
|
||||
CryptoPP::SecByteBlock buffer(hash.DigestSize());
|
||||
hash.Final(buffer);
|
||||
|
||||
if ( handler->m_nEncryptRevision > 5 )
|
||||
{
|
||||
MakeFileKey3(sOwnerPassword, buffer.BytePtr(), buffer.SizeInBytes(), handler->m_seUserKey->GetUBuffer(), 48);
|
||||
}
|
||||
|
||||
bValidate = (0 == memcmp(buffer.BytePtr(), handler->m_seOwnerKey->GetUBuffer(), 32));
|
||||
|
||||
if (bValidate)
|
||||
@ -203,10 +249,15 @@ namespace PdfReader
|
||||
|
||||
CryptoPP::SecByteBlock buffer(hash.DigestSize());
|
||||
hash.Final(buffer);
|
||||
|
||||
if ( handler->m_nEncryptRevision > 5 )
|
||||
{
|
||||
MakeFileKey3(sOwnerPassword, buffer.BytePtr(), buffer.SizeInBytes(), handler->m_seUserKey->GetUBuffer(), 48);
|
||||
}
|
||||
|
||||
CryptoPP::AES::Decryption aesDecryption(buffer.BytePtr(), buffer.SizeInBytes());
|
||||
unsigned char* empty[16] = {};
|
||||
CryptoPP::CBC_Mode_ExternalCipher::Decryption cbcDecryption( aesDecryption, (unsigned char*)empty );
|
||||
unsigned char empty[16] = {};
|
||||
CryptoPP::CBC_Mode_ExternalCipher::Decryption cbcDecryption( aesDecryption, empty );
|
||||
|
||||
CryptoPP::StreamTransformationFilter stfDecryptor(cbcDecryption, new CryptoPP::ArraySink( (unsigned char*)handler->m_sFileKey, 32), CryptoPP::StreamTransformationFilter::NO_PADDING );
|
||||
stfDecryptor.Put(handler->m_seOwnerEncryptionKey->GetUBuffer(), 32);
|
||||
@ -216,9 +267,63 @@ namespace PdfReader
|
||||
handler->m_bOwnerPasswordValid = bValidate;
|
||||
return bValidate;
|
||||
}
|
||||
else if ( handler->m_nEncryptRevision == 6 )
|
||||
}
|
||||
|
||||
bool Decrypt::MakeFileKey3(const std::string &sPassword, unsigned char *pHash, int nHashSize, unsigned char *pHash2, int nHashSize2)
|
||||
{
|
||||
if (!pHash) return false;
|
||||
|
||||
int len = sPassword.length() < 127 ? sPassword.length() : 127;
|
||||
int size = 64 * (len + 64 + nHashSize2); // max
|
||||
|
||||
unsigned char K[64]; //max size sha
|
||||
unsigned char *K1 = new unsigned char[size];
|
||||
unsigned char *E = new unsigned char[size];
|
||||
|
||||
int hash_size = nHashSize;
|
||||
memcpy(K, pHash, nHashSize);
|
||||
|
||||
int iteration = 0;
|
||||
|
||||
while( (iteration < 64) || (iteration < E[size - 1] + 32))
|
||||
{
|
||||
CryptoPP::SecByteBlock key(K, 16), iv(K + 16, 16);
|
||||
|
||||
size = 0;
|
||||
for (int i = 0; i < 64; i++)
|
||||
{
|
||||
memcpy(K1 + size, sPassword.c_str(), len); size += len;
|
||||
memcpy(K1 + size, K, hash_size); size += hash_size;
|
||||
if (pHash2)
|
||||
{
|
||||
memcpy(K1 + size, pHash2, nHashSize2); size += nHashSize2;
|
||||
}
|
||||
}
|
||||
|
||||
CryptoPP::CBC_Mode< CryptoPP::AES >::Encryption encryption;
|
||||
encryption.SetKeyWithIV( key, key.size(), iv );
|
||||
|
||||
CryptoPP::StreamTransformationFilter stfEncryption(encryption, new CryptoPP::ArraySink( E, size), CryptoPP::StreamTransformationFilter::NO_PADDING );
|
||||
stfEncryption.Put2(K1, size, 1, true);
|
||||
stfEncryption.MessageEnd();
|
||||
//----------------------------------------------------------
|
||||
int E_mod_3 = 0;
|
||||
for (unsigned int i = 0; i < 16; ++i)
|
||||
{
|
||||
E_mod_3 += E[i];
|
||||
}
|
||||
E_mod_3 %= 3;
|
||||
|
||||
hash_size = SHA(E_mod_3, E, size, K);
|
||||
|
||||
iteration++;
|
||||
}
|
||||
|
||||
delete []K1;
|
||||
delete []E;
|
||||
|
||||
memcpy (pHash, K, 32); // pHash - from sha256
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Decrypt::MakeFileKey2(StandardSecurityHandler *handler, const std::string &sUserPassword)
|
||||
|
||||
@ -53,6 +53,7 @@ namespace PdfReader
|
||||
|
||||
private:
|
||||
|
||||
static bool MakeFileKey3(const std::string &sPassword, unsigned char *pHash, int nHashSize, unsigned char *pHash2 = NULL, int nHashSize2 = 0);
|
||||
static bool MakeFileKey2(StandardSecurityHandler *handler, const std::string &userPassword);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user