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()
const char* const pInput = "";
std::vector<unsigned char> calculate_hash =
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());
std::string aStr("cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e");
CPPUNIT_ASSERT_EQUAL(aStr, tostring(calculate_hash));
......@@ -112,7 +112,8 @@ void TestHash::testSHA512_saltspin()
const OUString aPass("pwd");
const OUString aAlgo("SHA-512");
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==");
CPPUNIT_ASSERT_EQUAL(aStr, aHash);
}
......
......@@ -263,7 +263,7 @@ css::uno::Sequence<sal_Int8> DocPasswordHelper::GetOoxHashAsSequence(
const rtl::OUString& rPassword,
const rtl::OUString& rSaltValue,
sal_uInt32 nSpinCount,
bool bPrependNotAppend,
comphelper::Hash::IterCount eIterCount,
const rtl::OUString& rAlgorithmName)
{
comphelper::HashType eType;
......@@ -287,7 +287,7 @@ css::uno::Sequence<sal_Int8> DocPasswordHelper::GetOoxHashAsSequence(
}
std::vector<unsigned char> hash( comphelper::Hash::calculateHash( rPassword, aSaltVec, nSpinCount,
bPrependNotAppend, eType));
eIterCount, eType));
return comphelper::containerToSequence<sal_Int8>( hash);
}
......@@ -296,11 +296,11 @@ OUString DocPasswordHelper::GetOoxHashAsBase64(
const rtl::OUString& rPassword,
const rtl::OUString& rSaltValue,
sal_uInt32 nSpinCount,
bool bPrependNotAppend,
comphelper::Hash::IterCount eIterCount,
const rtl::OUString& rAlgorithmName)
{
css::uno::Sequence<sal_Int8> aSeq( GetOoxHashAsSequence( rPassword, rSaltValue, nSpinCount,
bPrependNotAppend, rAlgorithmName));
eIterCount, rAlgorithmName));
OUStringBuffer aBuf;
comphelper::Base64::encode( aBuf, aSeq);
......
......@@ -157,7 +157,7 @@ std::vector<unsigned char> Hash::calculateHash(
const unsigned char* pInput, size_t nLength,
const unsigned char* pSalt, size_t nSaltLen,
sal_uInt32 nSpinCount,
bool bPrependNotAppend,
IterCount eIterCount,
HashType eType)
{
if (!pSalt)
......@@ -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/dd925430
// say the iteration is prepended to the hash.
const size_t nIterPos = (bPrependNotAppend ? 0 : hash.size());
const size_t nHashPos = (bPrependNotAppend ? 4 : 0);
std::vector<unsigned char> data( hash.size() + 4, 0);
const size_t nAddIter = (eIterCount == IterCount::NONE ? 0 : 4);
const size_t nIterPos = (eIterCount == IterCount::APPEND ? hash.size() : 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)
{
std::copy( hash.begin(), hash.end(), data.begin() + nHashPos);
if (nAddIter)
{
#ifdef OSL_BIGENDIAN
sal_uInt32 be = i;
sal_uInt8* p = reinterpret_cast<sal_uInt8*>(&be);
std::swap( p[0], p[3] );
std::swap( p[1], p[2] );
memcpy( data.data() + nIterPos, &be, 4);
sal_uInt32 be = i;
sal_uInt8* p = reinterpret_cast<sal_uInt8*>(&be);
std::swap( p[0], p[3] );
std::swap( p[1], p[2] );
memcpy( data.data() + nIterPos, &be, nAddIter);
#else
memcpy( data.data() + nIterPos, &i, 4);
memcpy( data.data() + nIterPos, &i, nAddIter);
#endif
}
/* TODO: isn't there something better than
* creating/finalizing/destroying on each iteration? */
Hash aReHash(eType);
......@@ -218,7 +222,7 @@ std::vector<unsigned char> Hash::calculateHash(
const OUString& rPassword,
const std::vector<unsigned char>& rSaltValue,
sal_uInt32 nSpinCount,
bool bPrependNotAppend,
IterCount eIterCount,
HashType eType)
{
const unsigned char* pPassBytes = reinterpret_cast<const unsigned char*>(rPassword.getStr());
......@@ -240,7 +244,7 @@ std::vector<unsigned char> Hash::calculateHash(
}
#endif
return calculateHash( pPassBytes, nPassBytesLen, rSaltValue.data(), rSaltValue.size(), nSpinCount,
bPrependNotAppend, eType);
eIterCount, eType);
}
}
......
......@@ -24,6 +24,7 @@
#include <comphelper/comphelperdllapi.h>
#include <vector>
#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 beans { struct PropertyValue; } } } }
......@@ -194,12 +195,14 @@ public:
@param nSpinCount
If >0 the number of repeated iterations.
@param bPrependNotAppend
If <FALSE/>, append spin count in iterations as per
@param eIterCount
If Hash::IterCount::APPEND, append iteration count as per
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/dd925430
If Hash::IterCount::NONE, do not add the iteration count to hash
iterations.
@param rAlgorithmName
One of "SHA-512", "SHA-256", ... as listed for AlgorithmName in
......@@ -216,7 +219,7 @@ public:
const rtl::OUString& rPassword,
const rtl::OUString& rSaltValue,
sal_uInt32 nSpinCount,
bool bPrependNotAppend,
comphelper::Hash::IterCount eIterCount,
const rtl::OUString& rAlgorithmName);
......@@ -234,12 +237,14 @@ public:
@param nSpinCount
If >0 the number of repeated iterations.
@param bPrependNotAppend
If <FALSE/>, append spin count in iterations as per
@param eIterCount
If Hash::IterCount::APPEND, append iteration count as per
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/dd925430
If Hash::IterCount::NONE, do not add the iteration count to hash
iterations.
@param rAlgorithmName
One of "SHA-512", "SHA-256", ... as listed for AlgorithmName in
......@@ -257,7 +262,7 @@ public:
const rtl::OUString& rPassword,
const rtl::OUString& rSaltValue,
sal_uInt32 nSpinCount,
bool bPrependNotAppend,
comphelper::Hash::IterCount eIterCount,
const rtl::OUString& rAlgorithmName);
......
......@@ -38,6 +38,13 @@ private:
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();
......@@ -50,10 +57,6 @@ public:
/** Calculate hash value with salt (pSalt,nSaltLen) prepended to password
(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
https://msdn.microsoft.com/en-us/library/dd920692 or
https://msdn.microsoft.com/en-us/library/dd924776 and
......@@ -62,12 +65,21 @@ public:
@param pSalt
may be nullptr thus no salt prepended
@param bPrependNotAppend
If <FALSE/>, append spin count in iterations as per
@param nSpinCount
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
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/dd925430
If IterCount::NONE, do not add the iteration count to hash
iterations.
@return the raw hash value
*/
......@@ -75,7 +87,7 @@ public:
const unsigned char* pInput, size_t nLength,
const unsigned char* pSalt, size_t nSaltLen,
sal_uInt32 nSpinCount,
bool bPrependNotAppend,
IterCount eIterCount,
HashType eType);
/** Convenience function to calculate a salted hash with iterations.
......@@ -90,7 +102,7 @@ public:
const rtl::OUString& rPassword,
const std::vector<unsigned char>& rSaltValue,
sal_uInt32 nSpinCount,
bool bPrependNotAppend,
IterCount eIterCount,
HashType eType);
size_t getLength() const;
......
......@@ -95,7 +95,7 @@ bool ScOoxPasswordHash::verifyPassword( const OUString& aPassText ) const
return false;
const OUString aHash( comphelper::DocPasswordHelper::GetOoxHashAsBase64(
aPassText, maSaltValue, mnSpinCount, false, maAlgorithmName));
aPassText, maSaltValue, mnSpinCount, comphelper::Hash::IterCount::APPEND, maAlgorithmName));
if (aHash.isEmpty())
// unsupported algorithm
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