Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound 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