[internal API] New OOXML password hashing and helper functions

Eike Rathke erack at redhat.com
Mon Mar 5 14:45:19 UTC 2018


Hi,

With a series of commits for
https://bugs.documentfoundation.org/show_bug.cgi?id=104250
and some follow-ups we now have functions to generate proper password
hash values as specified in OOXML, see also
https://msdn.microsoft.com/en-us/library/dd925430 (Standard Encrytpion)
https://msdn.microsoft.com/en-us/library/dd924776 (Agile Encryption)
https://msdn.microsoft.com/en-us/library/dd920692 (ISO Write Protection Method)

The actual "raw" implementation is in comphelper::Hash with

    static std::vector<unsigned char> calculateHash(
            const unsigned char* pInput, size_t nLength,
            const unsigned char* pSalt, size_t nSaltLen,
            sal_uInt32 nSpinCount,
            IterCount eIterCount,
            HashType eType);

and a convenience function that takes an UTF-16 encoded password string
and a vector with salt value

    static std::vector<unsigned char> calculateHash(
            const rtl::OUString& rPassword,
            const std::vector<unsigned char>& rSaltValue,
            sal_uInt32 nSpinCount,
            IterCount eIterCount,
            HashType eType);

See include/comphelper/hash.hxx and descriptions there.

Along with that there are some convenience and helper functions at
comphelper::DocPasswordHelper, see
include/comphelper/docpasswordhelper.hxx
and descriptions there.

    static css::uno::Sequence<sal_Int8> GetOoxHashAsSequence(
            const rtl::OUString& rPassword,
            const rtl::OUString& rSaltValue,
            sal_uInt32 nSpinCount,
            comphelper::Hash::IterCount eIterCount,
            const rtl::OUString& rAlgorithmName);

    static rtl::OUString GetOoxHashAsBase64(
            const rtl::OUString& rPassword,
            const rtl::OUString& rSaltValue,
            sal_uInt32 nSpinCount,
            comphelper::Hash::IterCount eIterCount,
            const rtl::OUString& rAlgorithmName);

    static std::vector<unsigned char> GetOoxHashAsVector(
            const rtl::OUString& rPassword,
            const std::vector<unsigned char>& rSaltValue,
            sal_uInt32 nSpinCount,
            comphelper::Hash::IterCount eIterCount,
            const rtl::OUString& rAlgorithmName);

Specifically GetOoxHashAsBase64() can be used to pass the strings
obtained from the OOXML file as they are and compare the result against
the document's hashValue string.

oox/source/crypto/AgileEngine.cxx
oox::core::AgileEngine::calculateHashFinal() now uses
comphelper::DocPasswordHelper::GetOoxHashAsVector()

Newer OOXML documents written by MS use "SHA512" (for encryption) or
"SHA-512" (for sheetProtection and fileSharing elelements and maybe
others) algorithm names. The helper functions accept both.

Note that to calculate hashes for new passwords a new salt value MUST be
generated and never existing salts reused, otherwise the whole purpose
of salts is defeated.. for this
comphelper::DocPasswordHelper::GenerateRandomByteSequence() can be used,
a length of 16 currently seems to be a common value.

Happy Hashing

  Eike

-- 
LibreOffice Calc developer. Number formatter stricken i18n transpositionizer.
GPG key 0x6A6CD5B765632D3A - 2265 D7F3 A7B0 95CC 3918  630B 6A6C D5B7 6563 2D3A
Care about Free Software, support the FSFE https://fsfe.org/support/?erack
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <https://lists.freedesktop.org/archives/libreoffice/attachments/20180305/ab789583/attachment.sig>


More information about the LibreOffice mailing list