diff options
author | weidai <weidai11@users.noreply.github.com> | 2004-04-08 01:57:33 +0000 |
---|---|---|
committer | weidai <weidai11@users.noreply.github.com> | 2004-04-08 01:57:33 +0000 |
commit | ea022976c4b7fe98c8b0f71ce97dcc4616973284 (patch) | |
tree | b8da570509087e1284ab7afeca281fee4b89836a /pwdbased.h | |
parent | 6569b7fe0b28d54721d707e990c7474273d05de9 (diff) | |
download | cryptopp-git-ea022976c4b7fe98c8b0f71ce97dcc4616973284.tar.gz |
add minimum iteration time option
Diffstat (limited to 'pwdbased.h')
-rw-r--r-- | pwdbased.h | 91 |
1 files changed, 71 insertions, 20 deletions
@@ -5,14 +5,20 @@ #include "cryptlib.h" #include "hmac.h" +#include "hrtimer.h" NAMESPACE_BEGIN(CryptoPP) +//! abstract base class for password based key derivation function class PasswordBasedKeyDerivationFunction { public: virtual unsigned int MaxDerivedKeyLength() const =0; - virtual void GeneralDeriveKey(byte *derived, unsigned int derivedLen, byte purpose, const byte *password, unsigned int passwordLen, const byte *salt, unsigned int saltLen, unsigned int iterations) const =0; + virtual bool UsesPurposeByte() const =0; + //! derive key from password + /*! If timeInSeconds != 0, will iterate until time elapsed, as measured by ThreadUserTimer + Returns actual iteration count, which is equal to iterations if timeInSeconds == 0, and not less than iterations otherwise. */ + virtual unsigned int DeriveKey(byte *derived, unsigned int derivedLen, byte purpose, const byte *password, unsigned int passwordLen, const byte *salt, unsigned int saltLen, unsigned int iterations, double timeInSeconds=0) const =0; }; //! PBKDF1 from PKCS #5, T should be a HashTransformation class @@ -21,10 +27,9 @@ class PKCS5_PBKDF1 : public PasswordBasedKeyDerivationFunction { public: unsigned int MaxDerivedKeyLength() const {return T::DIGESTSIZE;} + bool UsesPurposeByte() const {return false;} // PKCS #5 says PBKDF1 should only take 8-byte salts. This implementation allows salts of any length. - void GeneralDeriveKey(byte *derived, unsigned int derivedLen, byte ignored, const byte *password, unsigned int passwordLen, const byte *salt, unsigned int saltLen, unsigned int iterations) const - {DeriveKey(derived, derivedLen, password, passwordLen, salt, saltLen, iterations);} - void DeriveKey(byte *derived, unsigned int derivedLen, const byte *password, unsigned int passwordLen, const byte *salt, unsigned int saltLen=8, unsigned int iterations=1000) const; + unsigned int DeriveKey(byte *derived, unsigned int derivedLen, byte purpose, const byte *password, unsigned int passwordLen, const byte *salt, unsigned int saltLen, unsigned int iterations, double timeInSeconds=0) const; }; //! PBKDF2 from PKCS #5, T should be a HashTransformation class @@ -33,9 +38,8 @@ class PKCS5_PBKDF2_HMAC : public PasswordBasedKeyDerivationFunction { public: unsigned int MaxDerivedKeyLength() const {return 0xffffffffU;} // should multiply by T::DIGESTSIZE, but gets overflow that way - void GeneralDeriveKey(byte *derived, unsigned int derivedLen, byte ignored, const byte *password, unsigned int passwordLen, const byte *salt, unsigned int saltLen, unsigned int iterations) const - {DeriveKey(derived, derivedLen, password, passwordLen, salt, saltLen, iterations);} - void DeriveKey(byte *derived, unsigned int derivedLen, const byte *password, unsigned int passwordLen, const byte *salt, unsigned int saltLen, unsigned int iterations=1000) const; + bool UsesPurposeByte() const {return false;} + unsigned int DeriveKey(byte *derived, unsigned int derivedLen, byte purpose, const byte *password, unsigned int passwordLen, const byte *salt, unsigned int saltLen, unsigned int iterations, double timeInSeconds=0) const; }; /* @@ -49,10 +53,13 @@ public: */ template <class T> -void PKCS5_PBKDF1<T>::DeriveKey(byte *derived, unsigned int derivedLen, const byte *password, unsigned int passwordLen, const byte *salt, unsigned int saltLen, unsigned int iterations) const +unsigned int PKCS5_PBKDF1<T>::DeriveKey(byte *derived, unsigned int derivedLen, byte purpose, const byte *password, unsigned int passwordLen, const byte *salt, unsigned int saltLen, unsigned int iterations, double timeInSeconds) const { assert(derivedLen <= MaxDerivedKeyLength()); - assert(iterations > 0); + assert(iterations > 0 || timeInSeconds > 0); + + if (!iterations) + iterations = 1; T hash; hash.Update(password, passwordLen); @@ -61,20 +68,31 @@ void PKCS5_PBKDF1<T>::DeriveKey(byte *derived, unsigned int derivedLen, const by SecByteBlock buffer(hash.DigestSize()); hash.Final(buffer); - for (unsigned int i=1; i<iterations; i++) + unsigned int i; + ThreadUserTimer timer; + + if (timeInSeconds) + timer.StartTimer(); + + for (i=1; i<iterations || (timeInSeconds && (i%128!=0 || timer.ElapsedTimeAsDouble() < timeInSeconds)) : ; i++) hash.CalculateDigest(buffer, buffer, buffer.size()); memcpy(derived, buffer, derivedLen); + return i; } template <class T> -void PKCS5_PBKDF2_HMAC<T>::DeriveKey(byte *derived, unsigned int derivedLen, const byte *password, unsigned int passwordLen, const byte *salt, unsigned int saltLen, unsigned int iterations) const +unsigned int PKCS5_PBKDF2_HMAC<T>::DeriveKey(byte *derived, unsigned int derivedLen, byte purpose, const byte *password, unsigned int passwordLen, const byte *salt, unsigned int saltLen, unsigned int iterations, double timeInSeconds) const { assert(derivedLen <= MaxDerivedKeyLength()); - assert(iterations > 0); + assert(iterations > 0 || timeInSeconds > 0); + + if (!iterations) + iterations = 1; HMAC<T> hmac(password, passwordLen); SecByteBlock buffer(hmac.DigestSize()); + ThreadUserTimer timer; unsigned int i=1; while (derivedLen > 0) @@ -91,16 +109,30 @@ void PKCS5_PBKDF2_HMAC<T>::DeriveKey(byte *derived, unsigned int derivedLen, con unsigned int segmentLen = STDMIN(derivedLen, (unsigned int)buffer.size()); memcpy(derived, buffer, segmentLen); - for (j=1; j<iterations; j++) + if (timeInSeconds) + { + timeInSeconds = timeInSeconds / ((derivedLen + buffer.size() - 1) / buffer.size()); + timer.StartTimer(); + } + + for (j=1; j<iterations || (timeInSeconds && (j%128!=0 || timer.ElapsedTimeAsDouble() < timeInSeconds)); j++) { hmac.CalculateDigest(buffer, buffer, buffer.size()); xorbuf(derived, buffer, segmentLen); } + if (timeInSeconds) + { + iterations = j; + timeInSeconds = 0; + } + derived += segmentLen; derivedLen -= segmentLen; i++; } + + return iterations; } //! PBKDF from PKCS #12, appendix B, T should be a HashTransformation class @@ -109,16 +141,18 @@ class PKCS12_PBKDF : public PasswordBasedKeyDerivationFunction { public: unsigned int MaxDerivedKeyLength() const {return UINT_MAX;} - void GeneralDeriveKey(byte *derived, unsigned int derivedLen, byte purpose, const byte *password, unsigned int passwordLen, const byte *salt, unsigned int saltLen, unsigned int iterations) const - {DeriveKey(derived, derivedLen, purpose, password, passwordLen, salt, saltLen, iterations);} - void DeriveKey(byte *derived, unsigned int derivedLen, byte ID, const byte *password, unsigned int passwordLen, const byte *salt, unsigned int saltLen, unsigned int iterations=1000) const; + bool UsesPurposeByte() const {return true;} + unsigned int DeriveKey(byte *derived, unsigned int derivedLen, byte purpose, const byte *password, unsigned int passwordLen, const byte *salt, unsigned int saltLen, unsigned int iterations, double timeInSeconds) const; }; template <class T> -void PKCS12_PBKDF<T>::DeriveKey(byte *derived, unsigned int derivedLen, byte ID, const byte *password, unsigned int passwordLen, const byte *salt, unsigned int saltLen, unsigned int iterations) const +unsigned int PKCS12_PBKDF<T>::DeriveKey(byte *derived, unsigned int derivedLen, byte purpose, const byte *password, unsigned int passwordLen, const byte *salt, unsigned int saltLen, unsigned int iterations, double timeInSeconds) const { assert(derivedLen <= MaxDerivedKeyLength()); - assert(iterations > 0); + assert(iterations > 0 || timeInSeconds > 0); + + if (!iterations) + iterations = 1; const unsigned int v = T::BLOCKSIZE; // v is in bytes rather than bits as in PKCS #12 const unsigned int DLen = v, SLen = RoundUpToMultipleOf(saltLen, v); @@ -126,7 +160,7 @@ void PKCS12_PBKDF<T>::DeriveKey(byte *derived, unsigned int derivedLen, byte ID, SecByteBlock buffer(DLen + SLen + PLen); byte *D = buffer, *S = buffer+DLen, *P = buffer+DLen+SLen, *I = S; - memset(D, ID, DLen); + memset(D, purpose, DLen); unsigned int i; for (i=0; i<SLen; i++) S[i] = salt[i % saltLen]; @@ -136,12 +170,27 @@ void PKCS12_PBKDF<T>::DeriveKey(byte *derived, unsigned int derivedLen, byte ID, T hash; SecByteBlock Ai(T::DIGESTSIZE), B(v); + ThreadUserTimer timer; while (derivedLen > 0) { hash.CalculateDigest(Ai, buffer, buffer.size()); - for (i=1; i<iterations; i++) + + if (timeInSeconds) + { + timeInSeconds = timeInSeconds / ((derivedLen + Ai.size() - 1) / Ai.size()); + timer.StartTimer(); + } + + for (i=1; i<iterations || (timeInSeconds && (i%128!=0 || timer.ElapsedTimeAsDouble() < timeInSeconds)); i++) hash.CalculateDigest(Ai, Ai, Ai.size()); + + if (timeInSeconds) + { + iterations = i; + timeInSeconds = 0; + } + for (i=0; i<B.size(); i++) B[i] = Ai[i % Ai.size()]; @@ -155,6 +204,8 @@ void PKCS12_PBKDF<T>::DeriveKey(byte *derived, unsigned int derivedLen, byte ID, derived += segmentLen; derivedLen -= segmentLen; } + + return iterations; } NAMESPACE_END |