00001
00002
00003 #ifndef CRYPTOPP_PWDBASED_H
00004 #define CRYPTOPP_PWDBASED_H
00005
00006 #include "cryptlib.h"
00007 #include "hmac.h"
00008 #include "hrtimer.h"
00009
00010 NAMESPACE_BEGIN(CryptoPP)
00011
00012
00013 class PasswordBasedKeyDerivationFunction
00014 {
00015 public:
00016 virtual size_t MaxDerivedKeyLength() const =0;
00017 virtual bool UsesPurposeByte() const =0;
00018
00019
00020
00021 virtual unsigned int DeriveKey(byte *derived, size_t derivedLen, byte purpose, const byte *password, size_t passwordLen, const byte *salt, size_t saltLen, unsigned int iterations, double timeInSeconds=0) const =0;
00022 };
00023
00024
00025 template <class T>
00026 class PKCS5_PBKDF1 : public PasswordBasedKeyDerivationFunction
00027 {
00028 public:
00029 size_t MaxDerivedKeyLength() const {return T::DIGESTSIZE;}
00030 bool UsesPurposeByte() const {return false;}
00031
00032 unsigned int DeriveKey(byte *derived, size_t derivedLen, byte purpose, const byte *password, size_t passwordLen, const byte *salt, size_t saltLen, unsigned int iterations, double timeInSeconds=0) const;
00033 };
00034
00035
00036 template <class T>
00037 class PKCS5_PBKDF2_HMAC : public PasswordBasedKeyDerivationFunction
00038 {
00039 public:
00040 size_t MaxDerivedKeyLength() const {return 0xffffffffU;}
00041 bool UsesPurposeByte() const {return false;}
00042 unsigned int DeriveKey(byte *derived, size_t derivedLen, byte purpose, const byte *password, size_t passwordLen, const byte *salt, size_t saltLen, unsigned int iterations, double timeInSeconds=0) const;
00043 };
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055 template <class T>
00056 unsigned int PKCS5_PBKDF1<T>::DeriveKey(byte *derived, size_t derivedLen, byte purpose, const byte *password, size_t passwordLen, const byte *salt, size_t saltLen, unsigned int iterations, double timeInSeconds) const
00057 {
00058 assert(derivedLen <= MaxDerivedKeyLength());
00059 assert(iterations > 0 || timeInSeconds > 0);
00060
00061 if (!iterations)
00062 iterations = 1;
00063
00064 T hash;
00065 hash.Update(password, passwordLen);
00066 hash.Update(salt, saltLen);
00067
00068 SecByteBlock buffer(hash.DigestSize());
00069 hash.Final(buffer);
00070
00071 unsigned int i;
00072 ThreadUserTimer timer;
00073
00074 if (timeInSeconds)
00075 timer.StartTimer();
00076
00077 for (i=1; i<iterations || (timeInSeconds && (i%128!=0 || timer.ElapsedTimeAsDouble() < timeInSeconds)); i++)
00078 hash.CalculateDigest(buffer, buffer, buffer.size());
00079
00080 memcpy(derived, buffer, derivedLen);
00081 return i;
00082 }
00083
00084 template <class T>
00085 unsigned int PKCS5_PBKDF2_HMAC<T>::DeriveKey(byte *derived, size_t derivedLen, byte purpose, const byte *password, size_t passwordLen, const byte *salt, size_t saltLen, unsigned int iterations, double timeInSeconds) const
00086 {
00087 assert(derivedLen <= MaxDerivedKeyLength());
00088 assert(iterations > 0 || timeInSeconds > 0);
00089
00090 if (!iterations)
00091 iterations = 1;
00092
00093 HMAC<T> hmac(password, passwordLen);
00094 SecByteBlock buffer(hmac.DigestSize());
00095 ThreadUserTimer timer;
00096
00097 unsigned int i=1;
00098 while (derivedLen > 0)
00099 {
00100 hmac.Update(salt, saltLen);
00101 unsigned int j;
00102 for (j=0; j<4; j++)
00103 {
00104 byte b = byte(i >> ((3-j)*8));
00105 hmac.Update(&b, 1);
00106 }
00107 hmac.Final(buffer);
00108
00109 size_t segmentLen = STDMIN(derivedLen, buffer.size());
00110 memcpy(derived, buffer, segmentLen);
00111
00112 if (timeInSeconds)
00113 {
00114 timeInSeconds = timeInSeconds / ((derivedLen + buffer.size() - 1) / buffer.size());
00115 timer.StartTimer();
00116 }
00117
00118 for (j=1; j<iterations || (timeInSeconds && (j%128!=0 || timer.ElapsedTimeAsDouble() < timeInSeconds)); j++)
00119 {
00120 hmac.CalculateDigest(buffer, buffer, buffer.size());
00121 xorbuf(derived, buffer, segmentLen);
00122 }
00123
00124 if (timeInSeconds)
00125 {
00126 iterations = j;
00127 timeInSeconds = 0;
00128 }
00129
00130 derived += segmentLen;
00131 derivedLen -= segmentLen;
00132 i++;
00133 }
00134
00135 return iterations;
00136 }
00137
00138
00139 template <class T>
00140 class PKCS12_PBKDF : public PasswordBasedKeyDerivationFunction
00141 {
00142 public:
00143 size_t MaxDerivedKeyLength() const {return size_t(0)-1;}
00144 bool UsesPurposeByte() const {return true;}
00145 unsigned int DeriveKey(byte *derived, size_t derivedLen, byte purpose, const byte *password, size_t passwordLen, const byte *salt, size_t saltLen, unsigned int iterations, double timeInSeconds) const;
00146 };
00147
00148 template <class T>
00149 unsigned int PKCS12_PBKDF<T>::DeriveKey(byte *derived, size_t derivedLen, byte purpose, const byte *password, size_t passwordLen, const byte *salt, size_t saltLen, unsigned int iterations, double timeInSeconds) const
00150 {
00151 assert(derivedLen <= MaxDerivedKeyLength());
00152 assert(iterations > 0 || timeInSeconds > 0);
00153
00154 if (!iterations)
00155 iterations = 1;
00156
00157 const size_t v = T::BLOCKSIZE;
00158 const size_t DLen = v, SLen = RoundUpToMultipleOf(saltLen, v);
00159 const size_t PLen = RoundUpToMultipleOf(passwordLen, v), ILen = SLen + PLen;
00160 SecByteBlock buffer(DLen + SLen + PLen);
00161 byte *D = buffer, *S = buffer+DLen, *P = buffer+DLen+SLen, *I = S;
00162
00163 memset(D, purpose, DLen);
00164 size_t i;
00165 for (i=0; i<SLen; i++)
00166 S[i] = salt[i % saltLen];
00167 for (i=0; i<PLen; i++)
00168 P[i] = password[i % passwordLen];
00169
00170
00171 T hash;
00172 SecByteBlock Ai(T::DIGESTSIZE), B(v);
00173 ThreadUserTimer timer;
00174
00175 while (derivedLen > 0)
00176 {
00177 hash.CalculateDigest(Ai, buffer, buffer.size());
00178
00179 if (timeInSeconds)
00180 {
00181 timeInSeconds = timeInSeconds / ((derivedLen + Ai.size() - 1) / Ai.size());
00182 timer.StartTimer();
00183 }
00184
00185 for (i=1; i<iterations || (timeInSeconds && (i%128!=0 || timer.ElapsedTimeAsDouble() < timeInSeconds)); i++)
00186 hash.CalculateDigest(Ai, Ai, Ai.size());
00187
00188 if (timeInSeconds)
00189 {
00190 iterations = (unsigned int)i;
00191 timeInSeconds = 0;
00192 }
00193
00194 for (i=0; i<B.size(); i++)
00195 B[i] = Ai[i % Ai.size()];
00196
00197 Integer B1(B, B.size());
00198 ++B1;
00199 for (i=0; i<ILen; i+=v)
00200 (Integer(I+i, v) + B1).Encode(I+i, v);
00201
00202 size_t segmentLen = STDMIN(derivedLen, Ai.size());
00203 memcpy(derived, Ai, segmentLen);
00204 derived += segmentLen;
00205 derivedLen -= segmentLen;
00206 }
00207
00208 return iterations;
00209 }
00210
00211 NAMESPACE_END
00212
00213 #endif