PdfReader - decrypt files revision 6(fix bug #17002)

This commit is contained in:
ElenaSubbotina
2018-05-16 18:24:41 +03:00
parent 889a1f827a
commit b082ffe20c
3 changed files with 130 additions and 23 deletions

View File

@ -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;
}

View File

@ -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)

View File

@ -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);
};