Crypto++  5.6.5
Free C++ class library of cryptographic schemes
pwdbased.h
Go to the documentation of this file.
1 // pwdbased.h - written and placed in the public domain by Wei Dai
2 
3 //! \file pwdbased.h
4 //! \brief Password based key derivation functions
5 
6 #ifndef CRYPTOPP_PWDBASED_H
7 #define CRYPTOPP_PWDBASED_H
8 
9 #include "cryptlib.h"
10 #include "hrtimer.h"
11 #include "integer.h"
12 #include "hmac.h"
13 
14 NAMESPACE_BEGIN(CryptoPP)
15 
16 //! \brief Abstract base class for password based key derivation function
18 {
19 public:
20  virtual ~PasswordBasedKeyDerivationFunction() {}
21 
22  //! \brief Provides the maximum derived key length
23  //! \returns maximum derived key length, in bytes
24  virtual size_t MaxDerivedKeyLength() const =0;
25 
26  //! \brief Determines if the derivation function uses the purpose byte
27  //! \returns true if the derivation function uses the purpose byte, false otherwise
28  virtual bool UsesPurposeByte() const =0;
29 
30  //! \brief Derive key from the password
31  //! \param derived the byte buffer to receive the derived password
32  //! \param derivedLen the size of the byte buffer to receive the derived password
33  //! \param purpose an octet indicating the purpose of the derivation
34  //! \param password the byte buffer with the password
35  //! \param passwordLen the size of the password, in bytes
36  //! \param salt the byte buffer with the salt
37  //! \param saltLen the size of the salt, in bytes
38  //! \param iterations the number of iterations to attempt
39  //! \param timeInSeconds the length of time the derivation function should execute
40  //! \returns iteration count achieved
41  //! \details DeriveKey returns the actual iteration count achieved. If <tt>timeInSeconds == 0</tt>, then the complete number
42  //! of iterations will be obtained. If <tt>timeInSeconds != 0</tt>, then DeriveKey will iterate until time elapsed, as
43  //! measured by ThreadUserTimer.
44  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;
45 };
46 
47 //! \brief PBKDF1 from PKCS #5
48 //! \tparam T a HashTransformation class
49 template <class T>
51 {
52 public:
53  size_t MaxDerivedKeyLength() const {return T::DIGESTSIZE;}
54  bool UsesPurposeByte() const {return false;}
55  // PKCS #5 says PBKDF1 should only take 8-byte salts. This implementation allows salts of any length.
56  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;
57 };
58 
59 //! \brief PBKDF2 from PKCS #5
60 //! \tparam T a HashTransformation class
61 template <class T>
63 {
64 public:
65  size_t MaxDerivedKeyLength() const {return 0xffffffffU;} // should multiply by T::DIGESTSIZE, but gets overflow that way
66  bool UsesPurposeByte() const {return false;}
67  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;
68 };
69 
70 /*
71 class PBKDF2Params
72 {
73 public:
74  SecByteBlock m_salt;
75  unsigned int m_interationCount;
76  ASNOptional<ASNUnsignedWrapper<word32> > m_keyLength;
77 };
78 */
79 
80 template <class T>
81 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
82 {
83  CRYPTOPP_UNUSED(purpose);
84  CRYPTOPP_ASSERT(derivedLen <= MaxDerivedKeyLength());
85  CRYPTOPP_ASSERT(iterations > 0 || timeInSeconds > 0);
86 
87  if (!iterations)
88  iterations = 1;
89 
90  T hash;
91  hash.Update(password, passwordLen);
92  hash.Update(salt, saltLen);
93 
94  SecByteBlock buffer(hash.DigestSize());
95  hash.Final(buffer);
96 
97  unsigned int i;
98  ThreadUserTimer timer;
99 
100  if (timeInSeconds)
101  timer.StartTimer();
102 
103  for (i=1; i<iterations || (timeInSeconds && (i%128!=0 || timer.ElapsedTimeAsDouble() < timeInSeconds)); i++)
104  hash.CalculateDigest(buffer, buffer, buffer.size());
105 
106  memcpy(derived, buffer, derivedLen);
107  return i;
108 }
109 
110 template <class T>
111 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
112 {
113  CRYPTOPP_UNUSED(purpose);
114  CRYPTOPP_ASSERT(derivedLen <= MaxDerivedKeyLength());
115  CRYPTOPP_ASSERT(iterations > 0 || timeInSeconds > 0);
116 
117  if (!iterations)
118  iterations = 1;
119 
120  HMAC<T> hmac(password, passwordLen);
121  SecByteBlock buffer(hmac.DigestSize());
122  ThreadUserTimer timer;
123 
124  unsigned int i=1;
125  while (derivedLen > 0)
126  {
127  hmac.Update(salt, saltLen);
128  unsigned int j;
129  for (j=0; j<4; j++)
130  {
131  byte b = byte(i >> ((3-j)*8));
132  hmac.Update(&b, 1);
133  }
134  hmac.Final(buffer);
135 
136 #if CRYPTOPP_MSC_VERSION
137  const size_t segmentLen = STDMIN(derivedLen, buffer.size());
138  memcpy_s(derived, segmentLen, buffer, segmentLen);
139 #else
140  const size_t segmentLen = STDMIN(derivedLen, buffer.size());
141  memcpy(derived, buffer, segmentLen);
142 #endif
143 
144  if (timeInSeconds)
145  {
146  timeInSeconds = timeInSeconds / ((derivedLen + buffer.size() - 1) / buffer.size());
147  timer.StartTimer();
148  }
149 
150  for (j=1; j<iterations || (timeInSeconds && (j%128!=0 || timer.ElapsedTimeAsDouble() < timeInSeconds)); j++)
151  {
152  hmac.CalculateDigest(buffer, buffer, buffer.size());
153  xorbuf(derived, buffer, segmentLen);
154  }
155 
156  if (timeInSeconds)
157  {
158  iterations = j;
159  timeInSeconds = 0;
160  }
161 
162  derived += segmentLen;
163  derivedLen -= segmentLen;
164  i++;
165  }
166 
167  return iterations;
168 }
169 
170 //! \brief PBKDF from PKCS #12, appendix B
171 //! \tparam T a HashTransformation class
172 template <class T>
174 {
175 public:
176  size_t MaxDerivedKeyLength() const {return size_t(0)-1;}
177  bool UsesPurposeByte() const {return true;}
178  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;
179 };
180 
181 template <class T>
182 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
183 {
184  CRYPTOPP_ASSERT(derivedLen <= MaxDerivedKeyLength());
185  CRYPTOPP_ASSERT(iterations > 0 || timeInSeconds > 0);
186 
187  if (!iterations)
188  iterations = 1;
189 
190  const size_t v = T::BLOCKSIZE; // v is in bytes rather than bits as in PKCS #12
191  const size_t DLen = v, SLen = RoundUpToMultipleOf(saltLen, v);
192  const size_t PLen = RoundUpToMultipleOf(passwordLen, v), ILen = SLen + PLen;
193  SecByteBlock buffer(DLen + SLen + PLen);
194  byte *D = buffer, *S = buffer+DLen, *P = buffer+DLen+SLen, *I = S;
195 
196  memset(D, purpose, DLen);
197  size_t i;
198  for (i=0; i<SLen; i++)
199  S[i] = salt[i % saltLen];
200  for (i=0; i<PLen; i++)
201  P[i] = password[i % passwordLen];
202 
203 
204  T hash;
205  SecByteBlock Ai(T::DIGESTSIZE), B(v);
206  ThreadUserTimer timer;
207 
208  while (derivedLen > 0)
209  {
210  hash.CalculateDigest(Ai, buffer, buffer.size());
211 
212  if (timeInSeconds)
213  {
214  timeInSeconds = timeInSeconds / ((derivedLen + Ai.size() - 1) / Ai.size());
215  timer.StartTimer();
216  }
217 
218  for (i=1; i<iterations || (timeInSeconds && (i%128!=0 || timer.ElapsedTimeAsDouble() < timeInSeconds)); i++)
219  hash.CalculateDigest(Ai, Ai, Ai.size());
220 
221  if (timeInSeconds)
222  {
223  iterations = (unsigned int)i;
224  timeInSeconds = 0;
225  }
226 
227  for (i=0; i<B.size(); i++)
228  B[i] = Ai[i % Ai.size()];
229 
230  Integer B1(B, B.size());
231  ++B1;
232  for (i=0; i<ILen; i+=v)
233  (Integer(I+i, v) + B1).Encode(I+i, v);
234 
235 #if CRYPTOPP_MSC_VERSION
236  const size_t segmentLen = STDMIN(derivedLen, Ai.size());
237  memcpy_s(derived, segmentLen, Ai, segmentLen);
238 #else
239  const size_t segmentLen = STDMIN(derivedLen, Ai.size());
240  std::memcpy(derived, Ai, segmentLen);
241 #endif
242 
243  derived += segmentLen;
244  derivedLen -= segmentLen;
245  }
246 
247  return iterations;
248 }
249 
250 NAMESPACE_END
251 
252 #endif
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
Derive key from the password.
Definition: pwdbased.h:81
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
Derive key from the password.
Definition: pwdbased.h:182
Abstract base class for password based key derivation function.
Definition: pwdbased.h:17
Abstract base classes that provide a uniform interface to this library.
void memcpy_s(void *dest, size_t sizeInBytes, const void *src, size_t count)
Bounds checking replacement for memcpy()
Definition: misc.h:366
size_type size() const
Provides the count of elements in the SecBlock.
Definition: secblock.h:524
SecBlock typedef.
Definition: secblock.h:731
size_t MaxDerivedKeyLength() const
Provides the maximum derived key length.
Definition: pwdbased.h:65
PBKDF2 from PKCS #5.
Definition: pwdbased.h:62
bool UsesPurposeByte() const
Determines if the derivation function uses the purpose byte.
Definition: pwdbased.h:54
size_t MaxDerivedKeyLength() const
Provides the maximum derived key length.
Definition: pwdbased.h:176
PBKDF1 from PKCS #5.
Definition: pwdbased.h:50
bool UsesPurposeByte() const
Determines if the derivation function uses the purpose byte.
Definition: pwdbased.h:177
size_t MaxDerivedKeyLength() const
Provides the maximum derived key length.
Definition: pwdbased.h:53
Classes for HMAC message authentication codes.
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
Derive key from the password.
Definition: pwdbased.h:111
PBKDF from PKCS #12, appendix B.
Definition: pwdbased.h:173
unsigned int DigestSize() const
Provides the digest size of the hash.
Definition: hmac.h:28
bool UsesPurposeByte() const
Determines if the derivation function uses the purpose byte.
Definition: pwdbased.h:66
Multiple precision integer with arithmetic operations.
Definition: integer.h:43
void Update(const byte *input, size_t length)
Updates a hash with additional input.
Definition: hmac.cpp:60
const T & STDMIN(const T &a, const T &b)
Replacement function for std::min.
Definition: misc.h:477
#define CRYPTOPP_ASSERT(exp)
Debugging and diagnostic assertion.
Definition: trap.h:62
virtual void CalculateDigest(byte *digest, const byte *input, size_t length)
Updates the hash with additional input and computes the hash of the current message.
Definition: cryptlib.h:1003
HMAC.
Definition: hmac.h:50
void xorbuf(byte *buf, const byte *mask, size_t count)
Performs an XOR of a buffer with a mask.
Definition: misc.cpp:28
Multiple precision integer with arithmetic operations.
T1 RoundUpToMultipleOf(const T1 &n, const T2 &m)
Rounds a value up to a multiple of a second value.
Definition: misc.h:905
Crypto++ library namespace.
Measure CPU time spent executing instructions of this thread (if supported by OS) ...
Definition: hrtimer.h:48
virtual void Final(byte *digest)
Computes the hash of the current message.
Definition: cryptlib.h:960