00001
00002
00003 #ifndef CRYPTOPP_PWDBASED_H
00004 #define CRYPTOPP_PWDBASED_H
00005
00006 #include "cryptlib.h"
00007 #include "hmac.h"
00008
00009 NAMESPACE_BEGIN(CryptoPP)
00010
00011 class PasswordBasedKeyDerivationFunction
00012 {
00013 public:
00014 virtual unsigned int MaxDerivedKeyLength() const =0;
00015 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;
00016 };
00017
00018
00019 template <class T>
00020 class PKCS5_PBKDF1 : public PasswordBasedKeyDerivationFunction
00021 {
00022 public:
00023 unsigned int MaxDerivedKeyLength() const {return T::DIGESTSIZE;}
00024
00025 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
00026 {DeriveKey(derived, derivedLen, password, passwordLen, salt, saltLen, iterations);}
00027 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;
00028 };
00029
00030
00031 template <class T>
00032 class PKCS5_PBKDF2_HMAC : public PasswordBasedKeyDerivationFunction
00033 {
00034 public:
00035 unsigned int MaxDerivedKeyLength() const {return 0xffffffffU;}
00036 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
00037 {DeriveKey(derived, derivedLen, password, passwordLen, salt, saltLen, iterations);}
00038 void DeriveKey(byte *derived, unsigned int derivedLen, const byte *password, unsigned int passwordLen, const byte *salt, unsigned int saltLen, unsigned int iterations=1000) const;
00039 };
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051 template <class T>
00052 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
00053 {
00054 assert(derivedLen <= MaxDerivedLength());
00055 assert(iterations > 0);
00056
00057 T hash;
00058 hash.Update(password, passwordLen);
00059 hash.Update(salt, saltLen);
00060
00061 SecByteBlock buffer(hash.DigestSize());
00062 hash.Final(buffer);
00063
00064 for (unsigned int i=1; i<iterations; i++)
00065 hash.CalculateDigest(buffer, buffer, buffer.size());
00066
00067 memcpy(derived, buffer, derivedLen);
00068 }
00069
00070 template <class T>
00071 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
00072 {
00073 assert(derivedLen <= MaxDerivedKeyLength());
00074 assert(iterations > 0);
00075
00076 HMAC<T> hmac(password, passwordLen);
00077 SecByteBlock buffer(hmac.DigestSize());
00078
00079 unsigned int i=1;
00080 while (derivedLen > 0)
00081 {
00082 hmac.Update(salt, saltLen);
00083 unsigned int j;
00084 for (j=0; j<4; j++)
00085 {
00086 byte b = i >> ((3-j)*8);
00087 hmac.Update(&b, 1);
00088 }
00089 hmac.Final(buffer);
00090
00091 unsigned int segmentLen = STDMIN(derivedLen, (unsigned int)buffer.size());
00092 memcpy(derived, buffer, segmentLen);
00093
00094 for (j=1; j<iterations; j++)
00095 {
00096 hmac.CalculateDigest(buffer, buffer, buffer.size());
00097 xorbuf(derived, buffer, segmentLen);
00098 }
00099
00100 derived += segmentLen;
00101 derivedLen -= segmentLen;
00102 i++;
00103 }
00104 }
00105
00106
00107 template <class T>
00108 class PKCS12_PBKDF : public PasswordBasedKeyDerivationFunction
00109 {
00110 public:
00111 unsigned int MaxDerivedKeyLength() const {return UINT_MAX;}
00112 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
00113 {DeriveKey(derived, derivedLen, purpose, password, passwordLen, salt, saltLen, iterations);}
00114 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;
00115 };
00116
00117 template <class T>
00118 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
00119 {
00120 assert(derivedLen <= MaxDerivedKeyLength());
00121 assert(iterations > 0);
00122
00123 const unsigned int v = T::BLOCKSIZE;
00124 const unsigned int DLen = v, SLen = RoundUpToMultipleOf(saltLen, v);
00125 const unsigned int PLen = RoundUpToMultipleOf(passwordLen, v), ILen = SLen + PLen;
00126 SecByteBlock buffer(DLen + SLen + PLen);
00127 byte *D = buffer, *S = buffer+DLen, *P = buffer+DLen+SLen, *I = S;
00128
00129 memset(D, ID, DLen);
00130 unsigned int i;
00131 for (i=0; i<SLen; i++)
00132 S[i] = salt[i % saltLen];
00133 for (i=0; i<PLen; i++)
00134 P[i] = password[i % passwordLen];
00135
00136
00137 T hash;
00138 SecByteBlock Ai(T::DIGESTSIZE), B(v);
00139
00140 while (derivedLen > 0)
00141 {
00142 hash.CalculateDigest(Ai, buffer, buffer.size());
00143 for (i=1; i<iterations; i++)
00144 hash.CalculateDigest(Ai, Ai, Ai.size());
00145 for (i=0; i<B.size(); i++)
00146 B[i] = Ai[i % Ai.size()];
00147
00148 Integer B1(B, B.size());
00149 ++B1;
00150 for (i=0; i<ILen; i+=v)
00151 (Integer(I+i, v) + B1).Encode(I+i, v);
00152
00153 unsigned int segmentLen = STDMIN(derivedLen, (unsigned int)Ai.size());
00154 memcpy(derived, Ai, segmentLen);
00155 derived += segmentLen;
00156 derivedLen -= segmentLen;
00157 }
00158 }
00159
00160 NAMESPACE_END
00161
00162 #endif