Kaydet (Commit) 5a1fabb9 authored tarafından Eike Rathke's avatar Eike Rathke

Introduce enum comphelper::Hash::IterCount instead of bool

Clarifies intention, and with IterCount::NONE prepared to handle
something like old PBKDF1, if anything actually used that. See
https://tools.ietf.org/html/rfc8018#section-5.1 where iteration
count is not part of the re-hash.

Change-Id: I5f97ca7a91f611eced8ced0a0c64961c04535d36
üst 7c30bf05
...@@ -99,7 +99,7 @@ void TestHash::testSHA512_NoSaltNoSpin() ...@@ -99,7 +99,7 @@ void TestHash::testSHA512_NoSaltNoSpin()
const char* const pInput = ""; const char* const pInput = "";
std::vector<unsigned char> calculate_hash = std::vector<unsigned char> calculate_hash =
comphelper::Hash::calculateHash( reinterpret_cast<const unsigned char*>(pInput), 0, comphelper::Hash::calculateHash( reinterpret_cast<const unsigned char*>(pInput), 0,
nullptr, 0, 0, false, comphelper::HashType::SHA512); nullptr, 0, 0, comphelper::Hash::IterCount::NONE, comphelper::HashType::SHA512);
CPPUNIT_ASSERT_EQUAL(size_t(64), calculate_hash.size()); CPPUNIT_ASSERT_EQUAL(size_t(64), calculate_hash.size());
std::string aStr("cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"); std::string aStr("cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e");
CPPUNIT_ASSERT_EQUAL(aStr, tostring(calculate_hash)); CPPUNIT_ASSERT_EQUAL(aStr, tostring(calculate_hash));
...@@ -112,7 +112,8 @@ void TestHash::testSHA512_saltspin() ...@@ -112,7 +112,8 @@ void TestHash::testSHA512_saltspin()
const OUString aPass("pwd"); const OUString aPass("pwd");
const OUString aAlgo("SHA-512"); const OUString aAlgo("SHA-512");
const OUString aSalt("876MLoKTq42+/DLp415iZQ=="); const OUString aSalt("876MLoKTq42+/DLp415iZQ==");
const OUString aHash = comphelper::DocPasswordHelper::GetOoxHashAsBase64( aPass, aSalt, 100000, false, aAlgo); const OUString aHash = comphelper::DocPasswordHelper::GetOoxHashAsBase64( aPass, aSalt, 100000,
comphelper::Hash::IterCount::APPEND, aAlgo);
const OUString aStr("5l3mgNHXpWiFaBPv5Yso1Xd/UifWvQWmlDnl/hsCYbFT2sJCzorjRmBCQ/3qeDu6Q/4+GIE8a1DsdaTwYh1q2g=="); const OUString aStr("5l3mgNHXpWiFaBPv5Yso1Xd/UifWvQWmlDnl/hsCYbFT2sJCzorjRmBCQ/3qeDu6Q/4+GIE8a1DsdaTwYh1q2g==");
CPPUNIT_ASSERT_EQUAL(aStr, aHash); CPPUNIT_ASSERT_EQUAL(aStr, aHash);
} }
......
...@@ -263,7 +263,7 @@ css::uno::Sequence<sal_Int8> DocPasswordHelper::GetOoxHashAsSequence( ...@@ -263,7 +263,7 @@ css::uno::Sequence<sal_Int8> DocPasswordHelper::GetOoxHashAsSequence(
const rtl::OUString& rPassword, const rtl::OUString& rPassword,
const rtl::OUString& rSaltValue, const rtl::OUString& rSaltValue,
sal_uInt32 nSpinCount, sal_uInt32 nSpinCount,
bool bPrependNotAppend, comphelper::Hash::IterCount eIterCount,
const rtl::OUString& rAlgorithmName) const rtl::OUString& rAlgorithmName)
{ {
comphelper::HashType eType; comphelper::HashType eType;
...@@ -287,7 +287,7 @@ css::uno::Sequence<sal_Int8> DocPasswordHelper::GetOoxHashAsSequence( ...@@ -287,7 +287,7 @@ css::uno::Sequence<sal_Int8> DocPasswordHelper::GetOoxHashAsSequence(
} }
std::vector<unsigned char> hash( comphelper::Hash::calculateHash( rPassword, aSaltVec, nSpinCount, std::vector<unsigned char> hash( comphelper::Hash::calculateHash( rPassword, aSaltVec, nSpinCount,
bPrependNotAppend, eType)); eIterCount, eType));
return comphelper::containerToSequence<sal_Int8>( hash); return comphelper::containerToSequence<sal_Int8>( hash);
} }
...@@ -296,11 +296,11 @@ OUString DocPasswordHelper::GetOoxHashAsBase64( ...@@ -296,11 +296,11 @@ OUString DocPasswordHelper::GetOoxHashAsBase64(
const rtl::OUString& rPassword, const rtl::OUString& rPassword,
const rtl::OUString& rSaltValue, const rtl::OUString& rSaltValue,
sal_uInt32 nSpinCount, sal_uInt32 nSpinCount,
bool bPrependNotAppend, comphelper::Hash::IterCount eIterCount,
const rtl::OUString& rAlgorithmName) const rtl::OUString& rAlgorithmName)
{ {
css::uno::Sequence<sal_Int8> aSeq( GetOoxHashAsSequence( rPassword, rSaltValue, nSpinCount, css::uno::Sequence<sal_Int8> aSeq( GetOoxHashAsSequence( rPassword, rSaltValue, nSpinCount,
bPrependNotAppend, rAlgorithmName)); eIterCount, rAlgorithmName));
OUStringBuffer aBuf; OUStringBuffer aBuf;
comphelper::Base64::encode( aBuf, aSeq); comphelper::Base64::encode( aBuf, aSeq);
......
...@@ -157,7 +157,7 @@ std::vector<unsigned char> Hash::calculateHash( ...@@ -157,7 +157,7 @@ std::vector<unsigned char> Hash::calculateHash(
const unsigned char* pInput, size_t nLength, const unsigned char* pInput, size_t nLength,
const unsigned char* pSalt, size_t nSaltLen, const unsigned char* pSalt, size_t nSaltLen,
sal_uInt32 nSpinCount, sal_uInt32 nSpinCount,
bool bPrependNotAppend, IterCount eIterCount,
HashType eType) HashType eType)
{ {
if (!pSalt) if (!pSalt)
...@@ -188,21 +188,25 @@ std::vector<unsigned char> Hash::calculateHash( ...@@ -188,21 +188,25 @@ std::vector<unsigned char> Hash::calculateHash(
// https://msdn.microsoft.com/en-us/library/dd924776 and // https://msdn.microsoft.com/en-us/library/dd924776 and
// https://msdn.microsoft.com/en-us/library/dd925430 // https://msdn.microsoft.com/en-us/library/dd925430
// say the iteration is prepended to the hash. // say the iteration is prepended to the hash.
const size_t nIterPos = (bPrependNotAppend ? 0 : hash.size()); const size_t nAddIter = (eIterCount == IterCount::NONE ? 0 : 4);
const size_t nHashPos = (bPrependNotAppend ? 4 : 0); const size_t nIterPos = (eIterCount == IterCount::APPEND ? hash.size() : 0);
std::vector<unsigned char> data( hash.size() + 4, 0); const size_t nHashPos = (eIterCount == IterCount::PREPEND ? nAddIter : 0);
std::vector<unsigned char> data( hash.size() + nAddIter, 0);
for (sal_uInt32 i = 0; i < nSpinCount; ++i) for (sal_uInt32 i = 0; i < nSpinCount; ++i)
{ {
std::copy( hash.begin(), hash.end(), data.begin() + nHashPos); std::copy( hash.begin(), hash.end(), data.begin() + nHashPos);
if (nAddIter)
{
#ifdef OSL_BIGENDIAN #ifdef OSL_BIGENDIAN
sal_uInt32 be = i; sal_uInt32 be = i;
sal_uInt8* p = reinterpret_cast<sal_uInt8*>(&be); sal_uInt8* p = reinterpret_cast<sal_uInt8*>(&be);
std::swap( p[0], p[3] ); std::swap( p[0], p[3] );
std::swap( p[1], p[2] ); std::swap( p[1], p[2] );
memcpy( data.data() + nIterPos, &be, 4); memcpy( data.data() + nIterPos, &be, nAddIter);
#else #else
memcpy( data.data() + nIterPos, &i, 4); memcpy( data.data() + nIterPos, &i, nAddIter);
#endif #endif
}
/* TODO: isn't there something better than /* TODO: isn't there something better than
* creating/finalizing/destroying on each iteration? */ * creating/finalizing/destroying on each iteration? */
Hash aReHash(eType); Hash aReHash(eType);
...@@ -218,7 +222,7 @@ std::vector<unsigned char> Hash::calculateHash( ...@@ -218,7 +222,7 @@ std::vector<unsigned char> Hash::calculateHash(
const OUString& rPassword, const OUString& rPassword,
const std::vector<unsigned char>& rSaltValue, const std::vector<unsigned char>& rSaltValue,
sal_uInt32 nSpinCount, sal_uInt32 nSpinCount,
bool bPrependNotAppend, IterCount eIterCount,
HashType eType) HashType eType)
{ {
const unsigned char* pPassBytes = reinterpret_cast<const unsigned char*>(rPassword.getStr()); const unsigned char* pPassBytes = reinterpret_cast<const unsigned char*>(rPassword.getStr());
...@@ -240,7 +244,7 @@ std::vector<unsigned char> Hash::calculateHash( ...@@ -240,7 +244,7 @@ std::vector<unsigned char> Hash::calculateHash(
} }
#endif #endif
return calculateHash( pPassBytes, nPassBytesLen, rSaltValue.data(), rSaltValue.size(), nSpinCount, return calculateHash( pPassBytes, nPassBytesLen, rSaltValue.data(), rSaltValue.size(), nSpinCount,
bPrependNotAppend, eType); eIterCount, eType);
} }
} }
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <comphelper/comphelperdllapi.h> #include <comphelper/comphelperdllapi.h>
#include <vector> #include <vector>
#include <comphelper/docpasswordrequest.hxx> #include <comphelper/docpasswordrequest.hxx>
#include <comphelper/hash.hxx>
namespace com { namespace sun { namespace star { namespace task { class XInteractionHandler; } } } } namespace com { namespace sun { namespace star { namespace task { class XInteractionHandler; } } } }
namespace com { namespace sun { namespace star { namespace beans { struct PropertyValue; } } } } namespace com { namespace sun { namespace star { namespace beans { struct PropertyValue; } } } }
...@@ -194,12 +195,14 @@ public: ...@@ -194,12 +195,14 @@ public:
@param nSpinCount @param nSpinCount
If >0 the number of repeated iterations. If >0 the number of repeated iterations.
@param bPrependNotAppend @param eIterCount
If <FALSE/>, append spin count in iterations as per If Hash::IterCount::APPEND, append iteration count as per
https://msdn.microsoft.com/en-us/library/dd920692 https://msdn.microsoft.com/en-us/library/dd920692
If <TRUE/>, prepend spin count in iterations as per If Hash::IterCount::PREPEND, prepend iteration count as per
https://msdn.microsoft.com/en-us/library/dd924776 and https://msdn.microsoft.com/en-us/library/dd924776 and
https://msdn.microsoft.com/en-us/library/dd925430 https://msdn.microsoft.com/en-us/library/dd925430
If Hash::IterCount::NONE, do not add the iteration count to hash
iterations.
@param rAlgorithmName @param rAlgorithmName
One of "SHA-512", "SHA-256", ... as listed for AlgorithmName in One of "SHA-512", "SHA-256", ... as listed for AlgorithmName in
...@@ -216,7 +219,7 @@ public: ...@@ -216,7 +219,7 @@ public:
const rtl::OUString& rPassword, const rtl::OUString& rPassword,
const rtl::OUString& rSaltValue, const rtl::OUString& rSaltValue,
sal_uInt32 nSpinCount, sal_uInt32 nSpinCount,
bool bPrependNotAppend, comphelper::Hash::IterCount eIterCount,
const rtl::OUString& rAlgorithmName); const rtl::OUString& rAlgorithmName);
...@@ -234,12 +237,14 @@ public: ...@@ -234,12 +237,14 @@ public:
@param nSpinCount @param nSpinCount
If >0 the number of repeated iterations. If >0 the number of repeated iterations.
@param bPrependNotAppend @param eIterCount
If <FALSE/>, append spin count in iterations as per If Hash::IterCount::APPEND, append iteration count as per
https://msdn.microsoft.com/en-us/library/dd920692 https://msdn.microsoft.com/en-us/library/dd920692
If <TRUE/>, prepend spin count in iterations as per If Hash::IterCount::PREPEND, prepend iteration count as per
https://msdn.microsoft.com/en-us/library/dd924776 and https://msdn.microsoft.com/en-us/library/dd924776 and
https://msdn.microsoft.com/en-us/library/dd925430 https://msdn.microsoft.com/en-us/library/dd925430
If Hash::IterCount::NONE, do not add the iteration count to hash
iterations.
@param rAlgorithmName @param rAlgorithmName
One of "SHA-512", "SHA-256", ... as listed for AlgorithmName in One of "SHA-512", "SHA-256", ... as listed for AlgorithmName in
...@@ -257,7 +262,7 @@ public: ...@@ -257,7 +262,7 @@ public:
const rtl::OUString& rPassword, const rtl::OUString& rPassword,
const rtl::OUString& rSaltValue, const rtl::OUString& rSaltValue,
sal_uInt32 nSpinCount, sal_uInt32 nSpinCount,
bool bPrependNotAppend, comphelper::Hash::IterCount eIterCount,
const rtl::OUString& rAlgorithmName); const rtl::OUString& rAlgorithmName);
......
...@@ -38,6 +38,13 @@ private: ...@@ -38,6 +38,13 @@ private:
public: public:
enum class IterCount
{
NONE, /// Iteration count not added to hash iterations.
PREPEND, /// Iteration count prepended to hash iterations.
APPEND /// Iteration count appended to hash iterations.
};
Hash(HashType eType); Hash(HashType eType);
~Hash(); ~Hash();
...@@ -50,10 +57,6 @@ public: ...@@ -50,10 +57,6 @@ public:
/** Calculate hash value with salt (pSalt,nSaltLen) prepended to password /** Calculate hash value with salt (pSalt,nSaltLen) prepended to password
(pInput,nLength) and repeated iterations run if nSpinCount>0. (pInput,nLength) and repeated iterations run if nSpinCount>0.
For repeated iterations, each iteration's result plus a 4 byte value
(0-based, little endian) containing the number of the iteration
appended to the hash value is the input for the next iteration.
This implements the algorithms as specified in This implements the algorithms as specified in
https://msdn.microsoft.com/en-us/library/dd920692 or https://msdn.microsoft.com/en-us/library/dd920692 or
https://msdn.microsoft.com/en-us/library/dd924776 and https://msdn.microsoft.com/en-us/library/dd924776 and
...@@ -62,12 +65,21 @@ public: ...@@ -62,12 +65,21 @@ public:
@param pSalt @param pSalt
may be nullptr thus no salt prepended may be nullptr thus no salt prepended
@param bPrependNotAppend @param nSpinCount
If <FALSE/>, append spin count in iterations as per If >0, repeat nSpinCount iterations. For each iteration, the
previous iteration's result plus a 4 byte value (0-based,
little endian) containing the number of the iteration prepended
or appended to the hash value is the input for the next
iteration.
@param eIterCount
If IterCount::APPEND, append iteration count as per
https://msdn.microsoft.com/en-us/library/dd920692 https://msdn.microsoft.com/en-us/library/dd920692
If <TRUE/>, prepend spin count in iterations as per If IterCount::PREPEND, prepend iteration count as per
https://msdn.microsoft.com/en-us/library/dd924776 and https://msdn.microsoft.com/en-us/library/dd924776 and
https://msdn.microsoft.com/en-us/library/dd925430 https://msdn.microsoft.com/en-us/library/dd925430
If IterCount::NONE, do not add the iteration count to hash
iterations.
@return the raw hash value @return the raw hash value
*/ */
...@@ -75,7 +87,7 @@ public: ...@@ -75,7 +87,7 @@ public:
const unsigned char* pInput, size_t nLength, const unsigned char* pInput, size_t nLength,
const unsigned char* pSalt, size_t nSaltLen, const unsigned char* pSalt, size_t nSaltLen,
sal_uInt32 nSpinCount, sal_uInt32 nSpinCount,
bool bPrependNotAppend, IterCount eIterCount,
HashType eType); HashType eType);
/** Convenience function to calculate a salted hash with iterations. /** Convenience function to calculate a salted hash with iterations.
...@@ -90,7 +102,7 @@ public: ...@@ -90,7 +102,7 @@ public:
const rtl::OUString& rPassword, const rtl::OUString& rPassword,
const std::vector<unsigned char>& rSaltValue, const std::vector<unsigned char>& rSaltValue,
sal_uInt32 nSpinCount, sal_uInt32 nSpinCount,
bool bPrependNotAppend, IterCount eIterCount,
HashType eType); HashType eType);
size_t getLength() const; size_t getLength() const;
......
...@@ -95,7 +95,7 @@ bool ScOoxPasswordHash::verifyPassword( const OUString& aPassText ) const ...@@ -95,7 +95,7 @@ bool ScOoxPasswordHash::verifyPassword( const OUString& aPassText ) const
return false; return false;
const OUString aHash( comphelper::DocPasswordHelper::GetOoxHashAsBase64( const OUString aHash( comphelper::DocPasswordHelper::GetOoxHashAsBase64(
aPassText, maSaltValue, mnSpinCount, false, maAlgorithmName)); aPassText, maSaltValue, mnSpinCount, comphelper::Hash::IterCount::APPEND, maAlgorithmName));
if (aHash.isEmpty()) if (aHash.isEmpty())
// unsupported algorithm // unsupported algorithm
return false; return false;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment