summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--vcl/inc/pdf/PDFEncryptorR6.hxx5
-rw-r--r--vcl/qa/cppunit/pdfexport/PDFEncryptionTest.cxx66
-rw-r--r--vcl/source/pdf/PDFEncryptorR6.cxx33
3 files changed, 82 insertions, 22 deletions
diff --git a/vcl/inc/pdf/PDFEncryptorR6.hxx b/vcl/inc/pdf/PDFEncryptorR6.hxx
index a8812fefcd21..56fe094469c6 100644
--- a/vcl/inc/pdf/PDFEncryptorR6.hxx
+++ b/vcl/inc/pdf/PDFEncryptorR6.hxx
@@ -146,14 +146,15 @@ public:
void setupEncryption(std::vector<sal_uInt8>& rEncryptionKey, sal_Int32 nObject) override;
- void setupEncryptionWithIV(std::vector<sal_uInt8>& rInitvector, std::vector<sal_uInt8>& rIV);
-
/** Encrypts using Algorithm 1.A: Encryption of data using the AES algorithms
*
* Described in ISO 32000-2:2020(E) - 7.6.3.3
*/
void encrypt(const void* pInput, sal_uInt64 nInputSize, std::vector<sal_uInt8>& rOutput,
sal_uInt64 nOutputsSize) override;
+
+ void encryptWithIV(const void* pInput, sal_uInt64 nInputSize, std::vector<sal_uInt8>& rOutput,
+ std::vector<sal_uInt8>& rIV);
};
} // end vcl::pdf
diff --git a/vcl/qa/cppunit/pdfexport/PDFEncryptionTest.cxx b/vcl/qa/cppunit/pdfexport/PDFEncryptionTest.cxx
index f4eeb2a9fd05..2126cc0eb7f7 100644
--- a/vcl/qa/cppunit/pdfexport/PDFEncryptionTest.cxx
+++ b/vcl/qa/cppunit/pdfexport/PDFEncryptionTest.cxx
@@ -356,8 +356,8 @@ CPPUNIT_TEST_FIXTURE(PDFEncryptionTest, testFileEncryption)
std::vector<sal_uInt8> aEncryptedBuffer;
vcl::pdf::PDFEncryptorR6 aEncryptor;
- aEncryptor.setupEncryptionWithIV(aKey, aIV);
- aEncryptor.encrypt(aData.data(), aData.size(), aEncryptedBuffer, aData.size());
+ aEncryptor.setupEncryption(aKey, 0);
+ aEncryptor.encryptWithIV(aData.data(), aData.size(), aEncryptedBuffer, aIV);
CPPUNIT_ASSERT_EQUAL(
std::string("d07efca5cce3c18fd8e344d45d826886d1774c5e1e310c971f8578924f848fc6"),
@@ -375,6 +375,68 @@ CPPUNIT_TEST_FIXTURE(PDFEncryptionTest, testFileEncryption)
comphelper::hashToString(aOutputString));
}
+std::vector<sal_uInt8> decrypt_AES_256_CBC(std::vector<sal_uInt8>& rKey,
+ std::vector<sal_uInt8>& rIV,
+ std::vector<sal_uInt8>& rEncryptedBuffer)
+{
+ std::vector<sal_uInt8> aDecryptedBuffer(rEncryptedBuffer.size());
+ comphelper::Decrypt aDecryptor(rKey, rIV, comphelper::CryptoType::AES_256_CBC);
+ aDecryptor.update(aDecryptedBuffer, rEncryptedBuffer);
+ return aDecryptedBuffer;
+}
+
+CPPUNIT_TEST_FIXTURE(PDFEncryptionTest, testFileEncryption_checkDifferentIV)
+{
+ // Check each call to encrypt is usign a different IV (initialization vector)
+
+ std::vector<sal_uInt8> aKey
+ = parseHex("90e657b78c0315610f3f421bd396ff635fa8fe3cf2ea399e7e1ae23e6185b4fc");
+
+ static constexpr const auto aData = std::to_array<sal_uInt8>({ 'a', 'b', 'c' });
+
+ vcl::pdf::PDFEncryptorR6 aEncryptor;
+ aEncryptor.setupEncryption(aKey, 0);
+
+ std::vector<sal_uInt8> aEncrypted_1;
+ aEncryptor.encrypt(aData.data(), aData.size(), aEncrypted_1, aData.size());
+ std::vector<sal_uInt8> aIV_1(aEncrypted_1.begin(), aEncrypted_1.begin() + 16);
+
+ std::vector<sal_uInt8> aEncrypted_2;
+ aEncryptor.encrypt(aData.data(), aData.size(), aEncrypted_2, aData.size());
+ std::vector<sal_uInt8> aIV_2(aEncrypted_2.begin(), aEncrypted_2.begin() + 16);
+
+ std::vector<sal_uInt8> aEncrypted_3;
+ aEncryptor.encrypt(aData.data(), aData.size(), aEncrypted_3, aData.size());
+ std::vector<sal_uInt8> aIV_3(aEncrypted_3.begin(), aEncrypted_3.begin() + 16);
+
+ // All IV should be different
+ CPPUNIT_ASSERT(!std::equal(aIV_1.begin(), aIV_1.end(), aIV_2.begin()));
+ CPPUNIT_ASSERT(!std::equal(aIV_1.begin(), aIV_1.end(), aIV_3.begin()));
+ CPPUNIT_ASSERT(!std::equal(aIV_2.begin(), aIV_2.end(), aIV_3.begin()));
+
+ {
+ std::vector<sal_uInt8> aEncrypted(aEncrypted_1.begin() + 16, aEncrypted_1.end());
+ // expected 'a', 'b', 'c' + padding
+ CPPUNIT_ASSERT_EQUAL(
+ std::string("6162630d0d0d0d0d0d0d0d0d0d0d0d0d"),
+ comphelper::hashToString(decrypt_AES_256_CBC(aKey, aIV_1, aEncrypted)));
+ }
+
+ {
+ std::vector<sal_uInt8> aEncrypted(aEncrypted_2.begin() + 16, aEncrypted_2.end());
+ CPPUNIT_ASSERT_EQUAL(
+ std::string("6162630d0d0d0d0d0d0d0d0d0d0d0d0d"),
+ comphelper::hashToString(decrypt_AES_256_CBC(aKey, aIV_2, aEncrypted)));
+ }
+
+ {
+ std::vector<sal_uInt8> aEncrypted(aEncrypted_3.begin() + 16, aEncrypted_3.end());
+ CPPUNIT_ASSERT_EQUAL(
+ std::string("6162630d0d0d0d0d0d0d0d0d0d0d0d0d"),
+ comphelper::hashToString(decrypt_AES_256_CBC(aKey, aIV_3, aEncrypted)));
+ }
+}
+
} // end anonymous namespace
CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/vcl/source/pdf/PDFEncryptorR6.cxx b/vcl/source/pdf/PDFEncryptorR6.cxx
index c16d7cb1a276..d951b738246f 100644
--- a/vcl/source/pdf/PDFEncryptorR6.cxx
+++ b/vcl/source/pdf/PDFEncryptorR6.cxx
@@ -256,28 +256,25 @@ class VCL_DLLPUBLIC EncryptionContext
{
private:
std::vector<sal_uInt8> maKey;
- std::vector<sal_uInt8> maInitVector;
public:
- EncryptionContext(std::vector<sal_uInt8> const& rKey, std::vector<sal_uInt8> const& rIV)
+ EncryptionContext(std::vector<sal_uInt8> const& rKey)
: maKey(rKey)
- , maInitVector(rIV)
{
}
- /** Algorithm 1.A: Encryption of data using the AES algorithms
- *
- **/
- void encrypt(const void* pInput, sal_uInt64 nInputSize, std::vector<sal_uInt8>& rOutput)
+ /** Algorithm 1.A: Encryption of data using the AES algorithms */
+ void encrypt(const void* pInput, sal_uInt64 nInputSize, std::vector<sal_uInt8>& rOutput,
+ std::vector<sal_uInt8>& rIV)
{
- comphelper::Encrypt aEncrypt(maKey, maInitVector, comphelper::CryptoType::AES_256_CBC);
+ comphelper::Encrypt aEncrypt(maKey, rIV, comphelper::CryptoType::AES_256_CBC);
const sal_uInt8* pInputBytes = static_cast<const sal_uInt8*>(pInput);
std::vector<sal_uInt8> aInput(pInputBytes, pInputBytes + nInputSize);
size_t nPaddedSize = addPaddingToVector(aInput, BLOCK_SIZE);
std::vector<sal_uInt8> aOutput(nPaddedSize);
aEncrypt.update(aOutput, aInput);
rOutput.resize(nPaddedSize + IV_SIZE);
- std::copy(maInitVector.begin(), maInitVector.end(), rOutput.begin());
+ std::copy(rIV.begin(), rIV.end(), rOutput.begin());
std::copy(aOutput.begin(), aOutput.end(), rOutput.begin() + IV_SIZE);
}
};
@@ -357,21 +354,21 @@ sal_uInt64 PDFEncryptorR6::calculateSizeIncludingHeader(sal_uInt64 nSize)
void PDFEncryptorR6::setupEncryption(std::vector<sal_uInt8>& rEncryptionKey, sal_Int32 /*nObject*/)
{
- std::vector<sal_uInt8> aInitVector;
- generateBytes(aInitVector, IV_SIZE);
- m_pEncryptionContext = std::make_unique<EncryptionContext>(rEncryptionKey, aInitVector);
+ m_pEncryptionContext = std::make_unique<EncryptionContext>(rEncryptionKey);
}
-void PDFEncryptorR6::setupEncryptionWithIV(std::vector<sal_uInt8>& rEncryptionKey,
- std::vector<sal_uInt8>& rInitvector)
+void PDFEncryptorR6::encrypt(const void* pInput, sal_uInt64 nInputSize,
+ std::vector<sal_uInt8>& rOutput, sal_uInt64 /*nOutputSize*/)
{
- m_pEncryptionContext = std::make_unique<EncryptionContext>(rEncryptionKey, rInitvector);
+ std::vector<sal_uInt8> aIV;
+ generateBytes(aIV, IV_SIZE);
+ m_pEncryptionContext->encrypt(pInput, nInputSize, rOutput, aIV);
}
-void PDFEncryptorR6::encrypt(const void* pInput, sal_uInt64 nInputSize,
- std::vector<sal_uInt8>& rOutput, sal_uInt64 /*nOutputSize*/)
+void PDFEncryptorR6::encryptWithIV(const void* pInput, sal_uInt64 nInputSize,
+ std::vector<sal_uInt8>& rOutput, std::vector<sal_uInt8>& rIV)
{
- m_pEncryptionContext->encrypt(pInput, nInputSize, rOutput);
+ m_pEncryptionContext->encrypt(pInput, nInputSize, rOutput, rIV);
}
} // end vcl::pdf