vcl/inc/pdf/PDFEncryptor.hxx       |   24 +++++++++++++++++----
 vcl/inc/pdf/pdfwriter_impl.hxx     |    3 --
 vcl/source/gdi/pdfwriter_impl.cxx  |    9 ++++---
 vcl/source/gdi/pdfwriter_impl2.cxx |   42 +++++++++++--------------------------
 vcl/source/pdf/PDFEncryptor.cxx    |   33 +++++++++++++++++++++++++++++
 5 files changed, 72 insertions(+), 39 deletions(-)

New commits:
commit 2630015100c66a5ec19f07d786b5d0aab7d7892a
Author:     Tomaž Vajngerl <[email protected]>
AuthorDate: Thu Nov 7 14:35:18 2024 +0100
Commit:     Miklos Vajna <[email protected]>
CommitDate: Mon Nov 25 09:53:30 2024 +0100

    pdf: move stream/string encryption into PDFEncryptor
    
    Change-Id: Ie710e51faa7d65686d72a03d1ef4ca40dff8c27e
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176215
    Tested-by: Jenkins CollaboraOffice <[email protected]>
    Reviewed-by: Miklos Vajna <[email protected]>

diff --git a/vcl/inc/pdf/PDFEncryptor.hxx b/vcl/inc/pdf/PDFEncryptor.hxx
index dca2255139e8..5b9f50492742 100644
--- a/vcl/inc/pdf/PDFEncryptor.hxx
+++ b/vcl/inc/pdf/PDFEncryptor.hxx
@@ -12,16 +12,22 @@
 
 #include <string_view>
 #include <rtl/cipher.h>
-#include <com/sun/star/uno/Reference.hxx>
+#include <rtl/ustring.hxx>
+#include <vector>
 
 namespace vcl
 {
 struct PDFEncryptionProperties;
 }
+
 namespace com::sun::star::beans
 {
 class XMaterialHolder;
 }
+namespace com::sun::star::uno
+{
+template <typename> class Reference;
+}
 
 namespace vcl::pdf
 {
@@ -38,6 +44,10 @@ private:
 
     sal_Int32 m_nKeyLength = 0; // key length, 16 or 5
     sal_Int32 m_nRC4KeyLength = 0; // key length, 16 or 10, to be input to the 
algorithm 3.1
+
+    /* set to true if the following stream must be encrypted, used inside 
writeBuffer() */
+    bool m_bEncryptThisStream = false;
+
 public:
     PDFEncryptor();
     ~PDFEncryptor();
@@ -45,9 +55,6 @@ public:
     /* used to cipher the stream data and for password management */
     rtlCipher m_aCipher = nullptr;
 
-    /* set to true if the following stream must be encrypted, used inside 
writeBuffer() */
-    bool m_bEncryptThisStream = false;
-
     sal_Int32 getAccessPermissions() { return m_nAccessPermissions; }
     sal_Int32 getKeyLength() { return m_nKeyLength; }
     sal_Int32 getRC4KeyLength() { return m_nRC4KeyLength; }
@@ -58,6 +65,15 @@ public:
         const css::uno::Reference<css::beans::XMaterialHolder>& 
xEncryptionMaterialHolder,
         PDFEncryptionProperties& rProperties);
     void setupKeysAndCheck(PDFEncryptionProperties& rProperties);
+
+    void setupEncryption(std::vector<sal_uInt8> const& rEncryptionKey, 
sal_Int32 nObject);
+    void enableStreamEncryption();
+    void disableStreamEncryption();
+
+    bool isStreamEncryptionEnabled() { return m_bEncryptThisStream; }
+
+    void encrypt(const void* pInput, sal_uInt64 nInputSize, sal_uInt8* pOutput,
+                 sal_uInt64 nOutputsSize);
 };
 }
 
diff --git a/vcl/inc/pdf/pdfwriter_impl.hxx b/vcl/inc/pdf/pdfwriter_impl.hxx
index 486363e83cf4..5756bebf0082 100644
--- a/vcl/inc/pdf/pdfwriter_impl.hxx
+++ b/vcl/inc/pdf/pdfwriter_impl.hxx
@@ -837,10 +837,9 @@ private:
 
     void addRoleMap(OString aAlias, PDFWriter::StructElement eType);
 
-    /* this function implements part of the PDF spec algorithm 3.1 in 
encryption, the rest (the actual encryption) is in PDFWriterImpl::writeBuffer */
     void checkAndEnableStreamEncryption( sal_Int32 nObject ) override;
 
-    void disableStreamEncryption() override { 
m_aPDFEncryptor.m_bEncryptThisStream = false; }
+    void disableStreamEncryption() override;
 
     /* */
     void enableStringEncryption( sal_Int32 nObject );
diff --git a/vcl/source/gdi/pdfwriter_impl.cxx 
b/vcl/source/gdi/pdfwriter_impl.cxx
index b6f916a560c1..893471b3a34b 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -1739,15 +1739,16 @@ bool PDFWriterImpl::writeBufferBytes( const void* 
pBuffer, sal_uInt64 nBytes )
     else
     {
         bool  buffOK = true;
-        if (m_aPDFEncryptor.m_bEncryptThisStream)
+        if (m_aPDFEncryptor.isStreamEncryptionEnabled())
         {
-            /* implement the encryption part of the PDF spec encryption 
algorithm 3.1 */
             m_vEncryptionBuffer.resize(nBytes);
             if (buffOK)
-                rtl_cipher_encodeARCFOUR(m_aPDFEncryptor.m_aCipher, pBuffer, 
static_cast<sal_Size>(nBytes), m_vEncryptionBuffer.data(), 
static_cast<sal_Size>(nBytes));
+            {
+                m_aPDFEncryptor.encrypt(pBuffer, nBytes, 
m_vEncryptionBuffer.data(), nBytes);
+            }
         }
 
-        const void* pWriteBuffer = (m_aPDFEncryptor.m_bEncryptThisStream && 
buffOK) ? m_vEncryptionBuffer.data()  : pBuffer;
+        const void* pWriteBuffer = 
(m_aPDFEncryptor.isStreamEncryptionEnabled() && buffOK) ? 
m_vEncryptionBuffer.data() : pBuffer;
         m_DocDigest.update(static_cast<unsigned char const*>(pWriteBuffer), 
static_cast<sal_uInt32>(nBytes));
 
         if (m_aFile.write(pWriteBuffer, nBytes, nWritten) != osl::File::E_None)
diff --git a/vcl/source/gdi/pdfwriter_impl2.cxx 
b/vcl/source/gdi/pdfwriter_impl2.cxx
index 0f309f375c20..547c0fb36896 100644
--- a/vcl/source/gdi/pdfwriter_impl2.cxx
+++ b/vcl/source/gdi/pdfwriter_impl2.cxx
@@ -1078,43 +1078,27 @@ void PDFWriterImpl::playMetafile( const GDIMetaFile& 
i_rMtf, vcl::PDFExtOutDevDa
 
 // Encryption methods
 
-void PDFWriterImpl::checkAndEnableStreamEncryption( sal_Int32 nObject )
+void PDFWriterImpl::checkAndEnableStreamEncryption(sal_Int32 nObject)
 {
-    if( !m_aContext.Encryption.Encrypt() )
+    if (!m_aContext.Encryption.Encrypt())
         return;
 
-    m_aPDFEncryptor.m_bEncryptThisStream = true;
-    sal_Int32 i = m_aPDFEncryptor.getKeyLength();
-    m_aContext.Encryption.EncryptionKey[i++] = static_cast<sal_uInt8>(nObject);
-    m_aContext.Encryption.EncryptionKey[i++] = static_cast<sal_uInt8>( nObject 
>> 8 );
-    m_aContext.Encryption.EncryptionKey[i++] = static_cast<sal_uInt8>( nObject 
>> 16 );
-    // the other location of m_nEncryptionKey is already set to 0, our fixed 
generation number
-    // do the MD5 hash
-    ::std::vector<unsigned char> const 
nMD5Sum(::comphelper::Hash::calculateHash(
-        m_aContext.Encryption.EncryptionKey.data(), i+2, 
::comphelper::HashType::MD5));
-    // the i+2 to take into account the generation number, always zero
-    // initialize the RC4 with the key
-    // key length: see algorithm 3.1, step 4: (N+5) max 16
-    rtl_cipher_initARCFOUR(m_aPDFEncryptor.m_aCipher, 
rtl_Cipher_DirectionEncode, nMD5Sum.data(), m_aPDFEncryptor.getRC4KeyLength(), 
nullptr, 0);
+    m_aPDFEncryptor.enableStreamEncryption();
+    m_aPDFEncryptor.setupEncryption(m_aContext.Encryption.EncryptionKey, 
nObject);
 }
 
-void PDFWriterImpl::enableStringEncryption( sal_Int32 nObject )
+void PDFWriterImpl::disableStreamEncryption()
 {
-    if( !m_aContext.Encryption.Encrypt() )
+    m_aPDFEncryptor.disableStreamEncryption();
+
+}
+
+void PDFWriterImpl::enableStringEncryption(sal_Int32 nObject)
+{
+    if (!m_aContext.Encryption.Encrypt())
         return;
 
-    sal_Int32 i = m_aPDFEncryptor.getKeyLength();
-    m_aContext.Encryption.EncryptionKey[i++] = static_cast<sal_uInt8>(nObject);
-    m_aContext.Encryption.EncryptionKey[i++] = static_cast<sal_uInt8>( nObject 
>> 8 );
-    m_aContext.Encryption.EncryptionKey[i++] = static_cast<sal_uInt8>( nObject 
>> 16 );
-    // the other location of m_nEncryptionKey is already set to 0, our fixed 
generation number
-    // do the MD5 hash
-    // the i+2 to take into account the generation number, always zero
-    ::std::vector<unsigned char> const 
nMD5Sum(::comphelper::Hash::calculateHash(
-        m_aContext.Encryption.EncryptionKey.data(), i+2, 
::comphelper::HashType::MD5));
-    // initialize the RC4 with the key
-    // key length: see algorithm 3.1, step 4: (N+5) max 16
-    rtl_cipher_initARCFOUR(m_aPDFEncryptor.m_aCipher, 
rtl_Cipher_DirectionEncode, nMD5Sum.data(), m_aPDFEncryptor.getRC4KeyLength(), 
nullptr, 0);
+    m_aPDFEncryptor.setupEncryption(m_aContext.Encryption.EncryptionKey, 
nObject);
 }
 
 const tools::Long unsetRun[256] =
diff --git a/vcl/source/pdf/PDFEncryptor.cxx b/vcl/source/pdf/PDFEncryptor.cxx
index 2c6d37296d42..16b88ec160b0 100644
--- a/vcl/source/pdf/PDFEncryptor.cxx
+++ b/vcl/source/pdf/PDFEncryptor.cxx
@@ -380,6 +380,7 @@ bool PDFEncryptor::prepareEncryption(
     return bSuccess;
 }
 
+/* this function implements part of the PDF spec algorithm 3.1 in encryption */
 void PDFEncryptor::setupKeysAndCheck(vcl::PDFEncryptionProperties& rProperties)
 {
     // sanity check
@@ -399,6 +400,38 @@ void 
PDFEncryptor::setupKeysAndCheck(vcl::PDFEncryptionProperties& rProperties)
     }
 }
 
+void PDFEncryptor::enableStreamEncryption() { m_bEncryptThisStream = true; }
+
+void PDFEncryptor::disableStreamEncryption() { m_bEncryptThisStream = false; }
+
+void PDFEncryptor::setupEncryption(std::vector<sal_uInt8> const& 
rEncryptionKey, sal_Int32 nObject)
+{
+    std::vector<sal_uInt8> aKey(rEncryptionKey.begin(), rEncryptionKey.begin() 
+ m_nKeyLength);
+    std::vector<sal_uInt8> aObjectArray{
+        sal_uInt8(nObject), sal_uInt8(nObject >> 8), sal_uInt8(nObject >> 16),
+        0, // generation number, always zero
+        0 // generation number, always zero
+    };
+    aKey.insert(aKey.end(), aObjectArray.begin(), aObjectArray.end());
+
+    // do the MD5 hash
+    auto const nMD5Sum
+        = comphelper::Hash::calculateHash(aKey.data(), aKey.size(), 
::comphelper::HashType::MD5);
+
+    // initialize the RC4 with the key
+    // key length: see algorithm 3.1, step 4: (N+5) max 16
+    rtl_cipher_initARCFOUR(m_aCipher, rtl_Cipher_DirectionEncode, 
nMD5Sum.data(), getRC4KeyLength(),
+                           nullptr, 0);
+}
+
+/* implement the encryption part of the PDF spec encryption algorithm 3.1 */
+void PDFEncryptor::encrypt(const void* pInput, sal_uInt64 nInputSize, 
sal_uInt8* pOutput,
+                           sal_uInt64 nOutputsSize)
+{
+    rtl_cipher_encodeARCFOUR(m_aCipher, pInput, sal_Size(nInputSize), pOutput,
+                             sal_Size(nOutputsSize));
+}
+
 } // end vcl::pdf
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Reply via email to