vcl/inc/pdf/PDFEncryptor.hxx | 46 ++++++++ vcl/inc/pdf/pdfwriter_impl.hxx | 27 +---- vcl/source/gdi/pdfwriter_impl.cxx | 194 +++++++++++++++++-------------------- vcl/source/gdi/pdfwriter_impl2.cxx | 14 +- 4 files changed, 150 insertions(+), 131 deletions(-)
New commits: commit 2f21f1651d63cc9510cfdb03138196e4d252b9ea Author: Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk> AuthorDate: Mon Nov 4 13:18:42 2024 +0100 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Mon Nov 11 09:47:37 2024 +0100 pdf: move some encryption code into PDFEncryptor class Refactored the code to make encryption easier to change. Change-Id: I24b831781d4acd6329838dbf2468e9df6efad41e Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176015 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Miklos Vajna <vmik...@collabora.com> diff --git a/vcl/inc/pdf/PDFEncryptor.hxx b/vcl/inc/pdf/PDFEncryptor.hxx new file mode 100644 index 000000000000..c93fc0bec9e9 --- /dev/null +++ b/vcl/inc/pdf/PDFEncryptor.hxx @@ -0,0 +1,46 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#pragma once + +#include <rtl/cipher.h> + +namespace vcl::pdf +{ +constexpr sal_Int32 ENCRYPTED_PWD_SIZE = 32; + +class PDFEncryptor +{ +public: + /* used to cipher the stream data and for password management */ + rtlCipher m_aCipher = nullptr; + + /* pad string used for password in Standard security handler */ + static const sal_uInt8 s_nPadString[ENCRYPTED_PWD_SIZE]; + + /* set to true if the following stream must be encrypted, used inside writeBuffer() */ + bool m_bEncryptThisStream = false; + + /* The encryption key, formed with the user password according to algorithm 3.2, + * maximum length is 16 bytes + 3 + 2 for 128 bit security */ + 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 + + PDFEncryptor() + { + /* prepare the cypher engine */ + m_aCipher = rtl_cipher_createARCFOUR(rtl_Cipher_ModeStream); + } + + ~PDFEncryptor() { rtl_cipher_destroyARCFOUR(m_aCipher); } +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/pdf/pdfwriter_impl.hxx b/vcl/inc/pdf/pdfwriter_impl.hxx index 54de33b52145..0ec6e2f92691 100644 --- a/vcl/inc/pdf/pdfwriter_impl.hxx +++ b/vcl/inc/pdf/pdfwriter_impl.hxx @@ -34,11 +34,11 @@ #include <pdf/ResourceDict.hxx> #include <pdf/BitmapID.hxx> #include <pdf/Matrix3.hxx> +#include <pdf/PDFEncryptor.hxx> #include <com/sun/star/lang/Locale.hpp> #include <com/sun/star/util/XURLTransformer.hpp> #include <osl/file.hxx> -#include <rtl/cipher.h> #include <rtl/strbuf.hxx> #include <rtl/ustring.hxx> #include <tools/gen.hxx> @@ -72,7 +72,6 @@ class SvStream; class SvMemoryStream; // the maximum password length -constexpr sal_Int32 ENCRYPTED_PWD_SIZE = 32; constexpr sal_Int32 MD5_DIGEST_SIZE = 16; // security 128 bit constexpr sal_Int32 SECUR_128BIT_KEY = 16; @@ -810,6 +809,8 @@ private: ExternalPDFStreams m_aExternalPDFStreams; + PDFEncryptor m_aPDFEncryptor; + /* output redirection; e.g. to accumulate content streams for XObjects */ @@ -835,22 +836,6 @@ private: } return nPosition; } -/* -variables for PDF security -i12626 -*/ -/* used to cipher the stream data and for password management */ - rtlCipher m_aCipher; - /* pad string used for password in Standard security handler */ - static const sal_uInt8 s_nPadString[ENCRYPTED_PWD_SIZE]; - - /* the encryption key, formed with the user password according to algorithm 3.2, maximum length is 16 bytes + 3 + 2 - for 128 bit security */ - sal_Int32 m_nKeyLength; // key length, 16 or 5 - sal_Int32 m_nRC4KeyLength; // 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; /* the numerical value of the access permissions, according to PDF spec, must be signed */ sal_Int32 m_nAccessPermissions; @@ -866,17 +851,19 @@ i12626 /* 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_bEncryptThisStream = false; }; + void disableStreamEncryption() override { m_aPDFEncryptor.m_bEncryptThisStream = false; }; /* */ void enableStringEncryption( sal_Int32 nObject ); -// test if the encryption is active, if yes than encrypt the unicode string and add to the OStringBuffer parameter +public: // Temporary for PDFStructureWriter + // test if the encryption is active, if yes than encrypt the unicode string and add to the OStringBuffer parameter void appendUnicodeTextStringEncrypt( const OUString& rInString, const sal_Int32 nInObjectNumber, OStringBuffer& rOutBuffer ); void appendLiteralStringEncrypt( std::u16string_view rInString, const sal_Int32 nInObjectNumber, OStringBuffer& rOutBuffer, rtl_TextEncoding nEnc = RTL_TEXTENCODING_ASCII_US ); void appendLiteralStringEncrypt( std::string_view rInString, const sal_Int32 nInObjectNumber, OStringBuffer& rOutBuffer ); +private: /* creates fonts and subsets that will be emitted later */ void registerGlyph(const sal_GlyphId, const vcl::font::PhysicalFontFace*, const LogicalFontInstance* pFont, const std::vector<sal_Ucs>&, sal_Int32, sal_uInt8&, sal_Int32&); void registerSimpleGlyph(const sal_GlyphId, const vcl::font::PhysicalFontFace*, const std::vector<sal_Ucs>&, sal_Int32, sal_uInt8&, sal_Int32&); diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx index 73e031edfe9b..48f6e19d1ce2 100644 --- a/vcl/source/gdi/pdfwriter_impl.cxx +++ b/vcl/source/gdi/pdfwriter_impl.cxx @@ -274,18 +274,52 @@ void appendDestinationName( const OUString& rString, OStringBuffer& rBuffer ) } } } +} // end anonymous namespace + +namespace vcl::pdf +{ +const sal_uInt8 PDFEncryptor::s_nPadString[32] = +{ + 0x28, 0xBF, 0x4E, 0x5E, 0x4E, 0x75, 0x8A, 0x41, 0x64, 0x00, 0x4E, 0x56, 0xFF, 0xFA, 0x01, 0x08, + 0x2E, 0x2E, 0x00, 0xB6, 0xD0, 0x68, 0x3E, 0x80, 0x2F, 0x0C, 0xA9, 0xFE, 0x64, 0x53, 0x69, 0x7A +}; +} + +namespace vcl +{ + +namespace +{ + +template < class GEOMETRY > +GEOMETRY lcl_convert( const MapMode& _rSource, const MapMode& _rDest, OutputDevice* _pPixelConversion, const GEOMETRY& _rObject ) +{ + GEOMETRY aPoint; + if ( MapUnit::MapPixel == _rSource.GetMapUnit() ) + { + aPoint = _pPixelConversion->PixelToLogic( _rObject, _rDest ); + } + else + { + aPoint = OutputDevice::LogicToLogic( _rObject, _rSource, _rDest ); + } + return aPoint; +} + +void removePlaceholderSE(std::vector<PDFStructureElement> & rStructure, PDFStructureElement& rEle); /** Writes the PDF structure to the string buffer. * * Structure elements like: objects, IDs, dictionaries, key/values, ... - * */ class PDFStructureWriter { OStringBuffer maLine; + PDFWriterImpl& mrWriterImpl; public: - PDFStructureWriter() + PDFStructureWriter(PDFWriterImpl& rWriterImpl) : maLine(1024) + , mrWriterImpl(rWriterImpl) { } @@ -334,37 +368,19 @@ public: appendLiteralString(pString, nSize, maLine); maLine.append(")"); } -}; - -} // end anonymous namespace - -namespace vcl -{ -const sal_uInt8 PDFWriterImpl::s_nPadString[32] = -{ - 0x28, 0xBF, 0x4E, 0x5E, 0x4E, 0x75, 0x8A, 0x41, 0x64, 0x00, 0x4E, 0x56, 0xFF, 0xFA, 0x01, 0x08, - 0x2E, 0x2E, 0x00, 0xB6, 0xD0, 0x68, 0x3E, 0x80, 0x2F, 0x0C, 0xA9, 0xFE, 0x64, 0x53, 0x69, 0x7A -}; -namespace -{ - -template < class GEOMETRY > -GEOMETRY lcl_convert( const MapMode& _rSource, const MapMode& _rDest, OutputDevice* _pPixelConversion, const GEOMETRY& _rObject ) -{ - GEOMETRY aPoint; - if ( MapUnit::MapPixel == _rSource.GetMapUnit() ) + void writeUnicodeEncrypt(std::string_view key, OUString const& rString, sal_Int32 nObject) { - aPoint = _pPixelConversion->PixelToLogic( _rObject, _rDest ); + maLine.append(key); + mrWriterImpl.appendUnicodeTextStringEncrypt(rString, nObject, maLine); } - else + + void writeLiteralEncrypt(std::string_view key, std::string_view value, sal_Int32 nObject) { - aPoint = OutputDevice::LogicToLogic( _rObject, _rSource, _rDest ); + maLine.append(key); + mrWriterImpl.appendLiteralStringEncrypt(value, nObject, maLine); } - return aPoint; -} - -void removePlaceholderSE(std::vector<PDFStructureElement> & rStructure, PDFStructureElement& rEle); +}; } // end anonymous namespace @@ -1310,10 +1326,6 @@ PDFWriterImpl::PDFWriterImpl( const PDFWriter::PDFWriterContext& rContext, m_aFile(m_aContext.URL), m_bOpen(false), m_DocDigest(::comphelper::HashType::MD5), - m_aCipher( nullptr ), - m_nKeyLength(0), - m_nRC4KeyLength(0), - m_bEncryptThisStream( false ), m_nAccessPermissions(0), m_rOuterFace( i_rOuterFace ) { @@ -1352,9 +1364,6 @@ PDFWriterImpl::PDFWriterImpl( const PDFWriter::PDFWriterContext& rContext, // setup DocInfo setupDocInfo(); - /* prepare the cypher engine, can be done in CTOR, free in DTOR */ - m_aCipher = rtl_cipher_createARCFOUR( rtl_Cipher_ModeStream ); - if( xEnc.is() ) prepareEncryption( xEnc ); @@ -1373,7 +1382,7 @@ PDFWriterImpl::PDFWriterImpl( const PDFWriter::PDFWriterContext& rContext, OSL_ENSURE( false, "encryption data failed sanity check, encryption disabled" ); } else // setup key lengths - m_nAccessPermissions = computeAccessPermissions( m_aContext.Encryption, m_nKeyLength, m_nRC4KeyLength ); + m_nAccessPermissions = computeAccessPermissions(m_aContext.Encryption, m_aPDFEncryptor.m_nKeyLength, m_aPDFEncryptor.m_nRC4KeyLength); } // write header @@ -1440,8 +1449,6 @@ PDFWriterImpl::~PDFWriterImpl() void PDFWriterImpl::dispose() { - if( m_aCipher ) - rtl_cipher_destroyARCFOUR( m_aCipher ); m_aPages.clear(); VirtualDevice::dispose(); } @@ -1616,7 +1623,7 @@ inline void PDFWriterImpl::appendUnicodeTextStringEncrypt( const OUString& rInSt *pCopy++ = static_cast<sal_uInt8>( aUnChar & 255 ); } //encrypt in place - rtl_cipher_encodeARCFOUR( m_aCipher, m_vEncryptionBuffer.data(), nChars, m_vEncryptionBuffer.data(), nChars ); + rtl_cipher_encodeARCFOUR( m_aPDFEncryptor.m_aCipher, m_vEncryptionBuffer.data(), nChars, m_vEncryptionBuffer.data(), nChars); //now append, hexadecimal (appendHex), the encrypted result for(int i = 0; i < nChars; i++) appendHex( m_vEncryptionBuffer[i], rOutBuffer ); @@ -1636,7 +1643,7 @@ inline void PDFWriterImpl::appendLiteralStringEncrypt( std::string_view rInStrin m_vEncryptionBuffer.resize(nChars); //encrypt the string in a buffer, then append it enableStringEncryption( nInObjectNumber ); - rtl_cipher_encodeARCFOUR( m_aCipher, rInString.data(), nChars, m_vEncryptionBuffer.data(), nChars ); + rtl_cipher_encodeARCFOUR(m_aPDFEncryptor.m_aCipher, rInString.data(), nChars, m_vEncryptionBuffer.data(), nChars); appendLiteralString( reinterpret_cast<char*>(m_vEncryptionBuffer.data()), nChars, rOutBuffer ); } else @@ -1744,17 +1751,15 @@ bool PDFWriterImpl::writeBufferBytes( const void* pBuffer, sal_uInt64 nBytes ) else { bool buffOK = true; - if( m_bEncryptThisStream ) + if (m_aPDFEncryptor.m_bEncryptThisStream) { /* implement the encryption part of the PDF spec encryption algorithm 3.1 */ m_vEncryptionBuffer.resize(nBytes); - if( buffOK ) - rtl_cipher_encodeARCFOUR( m_aCipher, - pBuffer, static_cast<sal_Size>(nBytes), - m_vEncryptionBuffer.data(), static_cast<sal_Size>(nBytes) ); + if (buffOK) + rtl_cipher_encodeARCFOUR(m_aPDFEncryptor.m_aCipher, pBuffer, static_cast<sal_Size>(nBytes), m_vEncryptionBuffer.data(), static_cast<sal_Size>(nBytes)); } - const void* pWriteBuffer = ( m_bEncryptThisStream && buffOK ) ? m_vEncryptionBuffer.data() : pBuffer; + const void* pWriteBuffer = (m_aPDFEncryptor.m_bEncryptThisStream && 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) @@ -5798,68 +5803,48 @@ sal_Int32 PDFWriterImpl::emitInfoDict( ) { sal_Int32 nObject = createObject(); - if( updateObject( nObject ) ) - { - OStringBuffer aLine(1024); - appendObjectID(nObject, aLine); - aLine.append("<<"); + if (!updateObject(nObject)) + return 0; - // These entries are deprecated in PDF 2.0 (in favor of XMP metadata) and shouldn't be written. - // Exception: CreationDate and ModDate (which we don't write) - if (m_aContext.Version < PDFWriter::PDFVersion::PDF_2_0) + PDFStructureWriter aWriter(*this); + aWriter.startObject(nObject); + aWriter.startDict(); + + // These entries are deprecated in PDF 2.0 (in favor of XMP metadata) and shouldn't be written. + // Exception: CreationDate and ModDate (which we don't write) + if (m_aContext.Version < PDFWriter::PDFVersion::PDF_2_0) + { + if (!m_aContext.DocumentInfo.Title.isEmpty()) { - if (!m_aContext.DocumentInfo.Title.isEmpty()) - { - aLine.append("/Title" ); - appendUnicodeTextStringEncrypt( m_aContext.DocumentInfo.Title, nObject, aLine ); - aLine.append(" " ); - } - if( !m_aContext.DocumentInfo.Author.isEmpty() ) - { - aLine.append( "/Author" ); - appendUnicodeTextStringEncrypt( m_aContext.DocumentInfo.Author, nObject, aLine ); - aLine.append( " " ); - } - if( !m_aContext.DocumentInfo.Subject.isEmpty() ) - { - aLine.append( "/Subject" ); - appendUnicodeTextStringEncrypt( m_aContext.DocumentInfo.Subject, nObject, aLine ); - aLine.append( " " ); - } - if( !m_aContext.DocumentInfo.Keywords.isEmpty() ) - { - aLine.append( "/Keywords" ); - appendUnicodeTextStringEncrypt( m_aContext.DocumentInfo.Keywords, nObject, aLine ); - aLine.append( " " ); - } - if( !m_aContext.DocumentInfo.Creator.isEmpty() ) - { - aLine.append( "/Creator" ); - appendUnicodeTextStringEncrypt( m_aContext.DocumentInfo.Creator, nObject, aLine ); - aLine.append( " " ); - } - if( !m_aContext.DocumentInfo.Producer.isEmpty() ) - { - aLine.append( "/Producer" ); - appendUnicodeTextStringEncrypt( m_aContext.DocumentInfo.Producer, nObject, aLine ); - aLine.append( " " ); - } + aWriter.writeUnicodeEncrypt("/Title", m_aContext.DocumentInfo.Title, nObject); } - - // Allowed in PDF 2.0 + if (!m_aContext.DocumentInfo.Author.isEmpty()) { - aLine.append("/CreationDate"); - appendLiteralStringEncrypt( m_aCreationDateString, nObject, aLine ); - aLine.append( " " ); + aWriter.writeUnicodeEncrypt("/Author", m_aContext.DocumentInfo.Author, nObject); + } + if (!m_aContext.DocumentInfo.Subject.isEmpty()) + { + aWriter.writeUnicodeEncrypt("/Subject", m_aContext.DocumentInfo.Subject, nObject); + } + if (!m_aContext.DocumentInfo.Keywords.isEmpty()) + { + aWriter.writeUnicodeEncrypt("/Keywords", m_aContext.DocumentInfo.Keywords, nObject); + } + if (!m_aContext.DocumentInfo.Creator.isEmpty()) + { + aWriter.writeUnicodeEncrypt("/Creator", m_aContext.DocumentInfo.Creator, nObject); + } + if (!m_aContext.DocumentInfo.Producer.isEmpty()) + { + aWriter.writeUnicodeEncrypt("/Producer", m_aContext.DocumentInfo.Producer, nObject); } - - aLine.append(">> "); - aLine.append("endobj " ); - - if (!writeBuffer(aLine)) - nObject = 0; } - else + // Allowed in PDF 2.0 + aWriter.writeLiteralEncrypt("/CreationDate", m_aCreationDateString, nObject); + aWriter.endDict(); + aWriter.endObject(); + + if (!writeBuffer(aWriter.getLine())) nObject = 0; return nObject; @@ -6113,7 +6098,7 @@ sal_Int32 PDFWriterImpl::emitEncrypt() if (updateObject(nObject)) { - PDFStructureWriter aWriter; + PDFStructureWriter aWriter(*this); aWriter.startObject(nObject); aWriter.startDict(); aWriter.write("/Filter", "/Standard"); @@ -6214,6 +6199,7 @@ bool PDFWriterImpl::emitTrailer() } aLine.append( "> ] " ); } + if( !aDocChecksum.isEmpty() ) { aLine.append( "/DocChecksum /" ); @@ -9703,7 +9689,7 @@ bool PDFWriterImpl::writeBitmapObject( const BitmapEmit& rObject, bool bMask ) m_vEncryptionBuffer[nChar++] = rColor.GetBlue(); } //encrypt the colorspace lookup table - rtl_cipher_encodeARCFOUR( m_aCipher, m_vEncryptionBuffer.data(), nChar, m_vEncryptionBuffer.data(), nChar ); + rtl_cipher_encodeARCFOUR(m_aPDFEncryptor.m_aCipher, m_vEncryptionBuffer.data(), nChar, m_vEncryptionBuffer.data(), nChar); //now queue the data for output nChar = 0; for( sal_uInt16 i = 0; i < pAccess->GetPaletteEntryCount(); i++ ) diff --git a/vcl/source/gdi/pdfwriter_impl2.cxx b/vcl/source/gdi/pdfwriter_impl2.cxx index 58fc31aafdf8..41ae9f12bfaa 100644 --- a/vcl/source/gdi/pdfwriter_impl2.cxx +++ b/vcl/source/gdi/pdfwriter_impl2.cxx @@ -1151,8 +1151,8 @@ void PDFWriterImpl::checkAndEnableStreamEncryption( sal_Int32 nObject ) if( !m_aContext.Encryption.Encrypt() ) return; - m_bEncryptThisStream = true; - sal_Int32 i = m_nKeyLength; + m_aPDFEncryptor.m_bEncryptThisStream = true; + sal_Int32 i = m_aPDFEncryptor.m_nKeyLength; 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 ); @@ -1163,7 +1163,7 @@ void PDFWriterImpl::checkAndEnableStreamEncryption( sal_Int32 nObject ) // 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_aCipher, rtl_Cipher_DirectionEncode, nMD5Sum.data(), m_nRC4KeyLength, nullptr, 0 ); + rtl_cipher_initARCFOUR(m_aPDFEncryptor.m_aCipher, rtl_Cipher_DirectionEncode, nMD5Sum.data(), m_aPDFEncryptor.m_nRC4KeyLength, nullptr, 0); } void PDFWriterImpl::enableStringEncryption( sal_Int32 nObject ) @@ -1171,7 +1171,7 @@ void PDFWriterImpl::enableStringEncryption( sal_Int32 nObject ) if( !m_aContext.Encryption.Encrypt() ) return; - sal_Int32 i = m_nKeyLength; + sal_Int32 i = m_aPDFEncryptor.m_nKeyLength; 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 ); @@ -1182,7 +1182,7 @@ void PDFWriterImpl::enableStringEncryption( sal_Int32 nObject ) 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_aCipher, rtl_Cipher_DirectionEncode, nMD5Sum.data(), m_nRC4KeyLength, nullptr, 0 ); + rtl_cipher_initARCFOUR(m_aPDFEncryptor.m_aCipher, rtl_Cipher_DirectionEncode, nMD5Sum.data(), m_aPDFEncryptor.m_nRC4KeyLength, nullptr, 0); } /* init the encryption engine @@ -1285,7 +1285,7 @@ void PDFWriterImpl::padPassword( std::u16string_view i_rPassword, sal_uInt8* o_p //pad it with standard byte string sal_Int32 i,y; for( i = nCurrentChar, y = 0 ; i < ENCRYPTED_PWD_SIZE; i++, y++ ) - o_pPaddedPW[i] = s_nPadString[y]; + o_pPaddedPW[i] = PDFEncryptor::s_nPadString[y]; } /********************************** @@ -1460,7 +1460,7 @@ bool PDFWriterImpl::computeUDictionaryValue( EncHashTransporter* i_pTransporter, for(sal_uInt32 i = MD5_DIGEST_SIZE; i < sal_uInt32(io_rProperties.UValue.size()); i++) io_rProperties.UValue[i] = 0; //steps 2 and 3 - aDigest.update(s_nPadString, sizeof(s_nPadString)); + aDigest.update(PDFEncryptor::s_nPadString, sizeof(PDFEncryptor::s_nPadString)); aDigest.update(io_rProperties.DocumentIdentifier.data(), io_rProperties.DocumentIdentifier.size()); ::std::vector<unsigned char> const nMD5Sum(aDigest.finalize());