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