summaryrefslogtreecommitdiff
path: root/pwdbased.h
diff options
context:
space:
mode:
authorweidai <weidai11@users.noreply.github.com>2004-04-08 01:57:33 +0000
committerweidai <weidai11@users.noreply.github.com>2004-04-08 01:57:33 +0000
commitea022976c4b7fe98c8b0f71ce97dcc4616973284 (patch)
treeb8da570509087e1284ab7afeca281fee4b89836a /pwdbased.h
parent6569b7fe0b28d54721d707e990c7474273d05de9 (diff)
downloadcryptopp-git-ea022976c4b7fe98c8b0f71ce97dcc4616973284.tar.gz
add minimum iteration time option
Diffstat (limited to 'pwdbased.h')
-rw-r--r--pwdbased.h91
1 files changed, 71 insertions, 20 deletions
diff --git a/pwdbased.h b/pwdbased.h
index ec9809d9..1387a488 100644
--- a/pwdbased.h
+++ b/pwdbased.h
@@ -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