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