Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members

pwdbased.h

00001 // pwdbased.h - written and placed in the public domain by Wei Dai 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 //! PBKDF1 from PKCS #5, T should be a HashTransformation class 00019 template <class T> 00020 class PKCS5_PBKDF1 : public PasswordBasedKeyDerivationFunction 00021 { 00022 public: 00023 unsigned int MaxDerivedKeyLength() const {return T::DIGESTSIZE;} 00024 // PKCS #5 says PBKDF1 should only take 8-byte salts. This implementation allows salts of any length. 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 //! PBKDF2 from PKCS #5, T should be a HashTransformation class 00031 template <class T> 00032 class PKCS5_PBKDF2_HMAC : public PasswordBasedKeyDerivationFunction 00033 { 00034 public: 00035 unsigned int MaxDerivedKeyLength() const {return 0xffffffffU;} // should multiply by T::DIGESTSIZE, but gets overflow that way 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 class PBKDF2Params 00043 { 00044 public: 00045 SecByteBlock m_salt; 00046 unsigned int m_interationCount; 00047 ASNOptional<ASNUnsignedWrapper<word32> > m_keyLength; 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 //! PBKDF from PKCS #12, appendix B, T should be a HashTransformation class 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; // v is in bytes rather than bits as in PKCS #12 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

Generated on Fri Aug 13 09:56:54 2004 for Crypto++ by doxygen 1.3.7