File indexing completed on 2025-01-18 09:55:07
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef CRYPTOPP_PWDBASED_H
0009 #define CRYPTOPP_PWDBASED_H
0010
0011 #include "cryptlib.h"
0012 #include "hrtimer.h"
0013 #include "integer.h"
0014 #include "argnames.h"
0015 #include "algparam.h"
0016 #include "hmac.h"
0017
0018 NAMESPACE_BEGIN(CryptoPP)
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028 template <class T>
0029 class PKCS5_PBKDF1 : public PasswordBasedKeyDerivationFunction
0030 {
0031 public:
0032 virtual ~PKCS5_PBKDF1() {}
0033
0034 static std::string StaticAlgorithmName () {
0035 const std::string name(std::string("PBKDF1(") +
0036 std::string(T::StaticAlgorithmName()) + std::string(")"));
0037 return name;
0038 }
0039
0040
0041 std::string AlgorithmName() const {
0042 return StaticAlgorithmName();
0043 }
0044
0045
0046 size_t MaxDerivedKeyLength() const {
0047 return static_cast<size_t>(T::DIGESTSIZE);
0048 }
0049
0050
0051 size_t GetValidDerivedLength(size_t keylength) const;
0052
0053
0054 virtual size_t DeriveKey(byte *derived, size_t derivedLen, const byte *secret, size_t secretLen,
0055 const NameValuePairs& params = g_nullNameValuePairs) const;
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077 size_t DeriveKey(byte *derived, size_t derivedLen, byte purpose, const byte *secret, size_t secretLen, const byte *salt, size_t saltLen, unsigned int iterations, double timeInSeconds=0) const;
0078
0079 protected:
0080
0081 const Algorithm & GetAlgorithm() const {
0082 return *this;
0083 }
0084 };
0085
0086 template <class T>
0087 size_t PKCS5_PBKDF1<T>::GetValidDerivedLength(size_t keylength) const
0088 {
0089 if (keylength > MaxDerivedKeyLength())
0090 return MaxDerivedKeyLength();
0091 return keylength;
0092 }
0093
0094 template <class T>
0095 size_t PKCS5_PBKDF1<T>::DeriveKey(byte *derived, size_t derivedLen,
0096 const byte *secret, size_t secretLen, const NameValuePairs& params) const
0097 {
0098 CRYPTOPP_ASSERT(secret );
0099 CRYPTOPP_ASSERT(derived && derivedLen);
0100 CRYPTOPP_ASSERT(derivedLen <= MaxDerivedKeyLength());
0101
0102 byte purpose = (byte)params.GetIntValueWithDefault("Purpose", 0);
0103 unsigned int iterations = (unsigned int)params.GetIntValueWithDefault("Iterations", 1);
0104
0105 double timeInSeconds = 0.0f;
0106 (void)params.GetValue("TimeInSeconds", timeInSeconds);
0107
0108 ConstByteArrayParameter salt;
0109 (void)params.GetValue(Name::Salt(), salt);
0110
0111 return DeriveKey(derived, derivedLen, purpose, secret, secretLen, salt.begin(), salt.size(), iterations, timeInSeconds);
0112 }
0113
0114 template <class T>
0115 size_t PKCS5_PBKDF1<T>::DeriveKey(byte *derived, size_t derivedLen, byte purpose, const byte *secret, size_t secretLen, const byte *salt, size_t saltLen, unsigned int iterations, double timeInSeconds) const
0116 {
0117 CRYPTOPP_ASSERT(secret );
0118 CRYPTOPP_ASSERT(derived && derivedLen);
0119 CRYPTOPP_ASSERT(derivedLen <= MaxDerivedKeyLength());
0120 CRYPTOPP_ASSERT(iterations > 0 || timeInSeconds > 0);
0121 CRYPTOPP_UNUSED(purpose);
0122
0123 ThrowIfInvalidDerivedKeyLength(derivedLen);
0124
0125
0126 if (!iterations) { iterations = 1; }
0127
0128 T hash;
0129 hash.Update(secret, secretLen);
0130 hash.Update(salt, saltLen);
0131
0132 SecByteBlock buffer(hash.DigestSize());
0133 hash.Final(buffer);
0134
0135 unsigned int i;
0136 ThreadUserTimer timer;
0137
0138 if (timeInSeconds)
0139 timer.StartTimer();
0140
0141 for (i=1; i<iterations || (timeInSeconds && (i%128!=0 || timer.ElapsedTimeAsDouble() < timeInSeconds)); i++)
0142 hash.CalculateDigest(buffer, buffer, buffer.size());
0143
0144 if (derived)
0145 std::memcpy(derived, buffer, derivedLen);
0146 return i;
0147 }
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157 template <class T>
0158 class PKCS5_PBKDF2_HMAC : public PasswordBasedKeyDerivationFunction
0159 {
0160 public:
0161 virtual ~PKCS5_PBKDF2_HMAC() {}
0162
0163 static std::string StaticAlgorithmName () {
0164 const std::string name(std::string("PBKDF2_HMAC(") +
0165 std::string(T::StaticAlgorithmName()) + std::string(")"));
0166 return name;
0167 }
0168
0169
0170 std::string AlgorithmName() const {
0171 return StaticAlgorithmName();
0172 }
0173
0174
0175
0176 size_t MaxDerivedKeyLength() const {
0177 return 0xffffffffU;
0178 }
0179
0180
0181 size_t GetValidDerivedLength(size_t keylength) const;
0182
0183
0184 size_t DeriveKey(byte *derived, size_t derivedLen, const byte *secret, size_t secretLen,
0185 const NameValuePairs& params = g_nullNameValuePairs) const;
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205 size_t DeriveKey(byte *derived, size_t derivedLen, byte purpose, const byte *secret, size_t secretLen,
0206 const byte *salt, size_t saltLen, unsigned int iterations, double timeInSeconds=0) const;
0207
0208 protected:
0209
0210 const Algorithm & GetAlgorithm() const {
0211 return *this;
0212 }
0213 };
0214
0215 template <class T>
0216 size_t PKCS5_PBKDF2_HMAC<T>::GetValidDerivedLength(size_t keylength) const
0217 {
0218 if (keylength > MaxDerivedKeyLength())
0219 return MaxDerivedKeyLength();
0220 return keylength;
0221 }
0222
0223 template <class T>
0224 size_t PKCS5_PBKDF2_HMAC<T>::DeriveKey(byte *derived, size_t derivedLen,
0225 const byte *secret, size_t secretLen, const NameValuePairs& params) const
0226 {
0227 CRYPTOPP_ASSERT(secret );
0228 CRYPTOPP_ASSERT(derived && derivedLen);
0229 CRYPTOPP_ASSERT(derivedLen <= MaxDerivedKeyLength());
0230
0231 byte purpose = (byte)params.GetIntValueWithDefault("Purpose", 0);
0232 unsigned int iterations = (unsigned int)params.GetIntValueWithDefault("Iterations", 1);
0233
0234 double timeInSeconds = 0.0f;
0235 (void)params.GetValue("TimeInSeconds", timeInSeconds);
0236
0237 ConstByteArrayParameter salt;
0238 (void)params.GetValue(Name::Salt(), salt);
0239
0240 return DeriveKey(derived, derivedLen, purpose, secret, secretLen, salt.begin(), salt.size(), iterations, timeInSeconds);
0241 }
0242
0243 template <class T>
0244 size_t PKCS5_PBKDF2_HMAC<T>::DeriveKey(byte *derived, size_t derivedLen, byte purpose, const byte *secret, size_t secretLen, const byte *salt, size_t saltLen, unsigned int iterations, double timeInSeconds) const
0245 {
0246 CRYPTOPP_ASSERT(secret );
0247 CRYPTOPP_ASSERT(derived && derivedLen);
0248 CRYPTOPP_ASSERT(derivedLen <= MaxDerivedKeyLength());
0249 CRYPTOPP_ASSERT(iterations > 0 || timeInSeconds > 0);
0250 CRYPTOPP_UNUSED(purpose);
0251
0252 ThrowIfInvalidDerivedKeyLength(derivedLen);
0253
0254
0255 if (!iterations) { iterations = 1; }
0256
0257
0258 HMAC<T> hmac(secret, secretLen);
0259 if (hmac.DigestSize() == 0)
0260 throw InvalidArgument("PKCS5_PBKDF2_HMAC: DigestSize cannot be 0");
0261
0262 SecByteBlock buffer(hmac.DigestSize());
0263 ThreadUserTimer timer;
0264
0265 unsigned int i=1;
0266 while (derivedLen > 0)
0267 {
0268 hmac.Update(salt, saltLen);
0269 unsigned int j;
0270 for (j=0; j<4; j++)
0271 {
0272 byte b = byte(i >> ((3-j)*8));
0273 hmac.Update(&b, 1);
0274 }
0275 hmac.Final(buffer);
0276
0277 #if CRYPTOPP_MSC_VERSION
0278 const size_t segmentLen = STDMIN(derivedLen, buffer.size());
0279 memcpy_s(derived, segmentLen, buffer, segmentLen);
0280 #else
0281 const size_t segmentLen = STDMIN(derivedLen, buffer.size());
0282 std::memcpy(derived, buffer, segmentLen);
0283 #endif
0284
0285 if (timeInSeconds)
0286 {
0287 timeInSeconds = timeInSeconds / ((derivedLen + buffer.size() - 1) / buffer.size());
0288 timer.StartTimer();
0289 }
0290
0291 for (j=1; j<iterations || (timeInSeconds && (j%128!=0 || timer.ElapsedTimeAsDouble() < timeInSeconds)); j++)
0292 {
0293 hmac.CalculateDigest(buffer, buffer, buffer.size());
0294 xorbuf(derived, buffer, segmentLen);
0295 }
0296
0297 if (timeInSeconds)
0298 {
0299 iterations = j;
0300 timeInSeconds = 0;
0301 }
0302
0303 derived += segmentLen;
0304 derivedLen -= segmentLen;
0305 i++;
0306 }
0307
0308 return iterations;
0309 }
0310
0311
0312
0313
0314
0315
0316
0317
0318
0319 template <class T>
0320 class PKCS12_PBKDF : public PasswordBasedKeyDerivationFunction
0321 {
0322 public:
0323 virtual ~PKCS12_PBKDF() {}
0324
0325 static std::string StaticAlgorithmName () {
0326 const std::string name(std::string("PBKDF_PKCS12(") +
0327 std::string(T::StaticAlgorithmName()) + std::string(")"));
0328 return name;
0329 }
0330
0331
0332 std::string AlgorithmName() const {
0333 return StaticAlgorithmName();
0334 }
0335
0336
0337 size_t MaxDerivedKeyLength() const {
0338 return static_cast<size_t>(-1);
0339 }
0340
0341
0342 size_t GetValidDerivedLength(size_t keylength) const;
0343
0344
0345 size_t DeriveKey(byte *derived, size_t derivedLen, const byte *secret, size_t secretLen,
0346 const NameValuePairs& params = g_nullNameValuePairs) const;
0347
0348
0349
0350
0351
0352
0353
0354
0355
0356
0357
0358
0359
0360
0361
0362
0363
0364
0365
0366 size_t DeriveKey(byte *derived, size_t derivedLen, byte purpose, const byte *secret, size_t secretLen,
0367 const byte *salt, size_t saltLen, unsigned int iterations, double timeInSeconds) const;
0368
0369 protected:
0370
0371 const Algorithm & GetAlgorithm() const {
0372 return *this;
0373 }
0374 };
0375
0376 template <class T>
0377 size_t PKCS12_PBKDF<T>::GetValidDerivedLength(size_t keylength) const
0378 {
0379 if (keylength > MaxDerivedKeyLength())
0380 return MaxDerivedKeyLength();
0381 return keylength;
0382 }
0383
0384 template <class T>
0385 size_t PKCS12_PBKDF<T>::DeriveKey(byte *derived, size_t derivedLen,
0386 const byte *secret, size_t secretLen, const NameValuePairs& params) const
0387 {
0388 CRYPTOPP_ASSERT(secret );
0389 CRYPTOPP_ASSERT(derived && derivedLen);
0390 CRYPTOPP_ASSERT(derivedLen <= MaxDerivedKeyLength());
0391
0392 byte purpose = (byte)params.GetIntValueWithDefault("Purpose", 0);
0393 unsigned int iterations = (unsigned int)params.GetIntValueWithDefault("Iterations", 1);
0394
0395 double timeInSeconds = 0.0f;
0396 (void)params.GetValue("TimeInSeconds", timeInSeconds);
0397
0398
0399 ConstByteArrayParameter salt;
0400 (void)params.GetValue(Name::Salt(), salt);
0401
0402 return DeriveKey(derived, derivedLen, purpose, secret, secretLen, salt.begin(), salt.size(), iterations, timeInSeconds);
0403 }
0404
0405 template <class T>
0406 size_t PKCS12_PBKDF<T>::DeriveKey(byte *derived, size_t derivedLen, byte purpose, const byte *secret, size_t secretLen, const byte *salt, size_t saltLen, unsigned int iterations, double timeInSeconds) const
0407 {
0408 CRYPTOPP_ASSERT(secret );
0409 CRYPTOPP_ASSERT(derived && derivedLen);
0410 CRYPTOPP_ASSERT(derivedLen <= MaxDerivedKeyLength());
0411 CRYPTOPP_ASSERT(iterations > 0 || timeInSeconds > 0);
0412
0413 ThrowIfInvalidDerivedKeyLength(derivedLen);
0414
0415
0416 if (!iterations) { iterations = 1; }
0417
0418 const size_t v = T::BLOCKSIZE;
0419 const size_t DLen = v, SLen = RoundUpToMultipleOf(saltLen, v);
0420 const size_t PLen = RoundUpToMultipleOf(secretLen, v), ILen = SLen + PLen;
0421 SecByteBlock buffer(DLen + SLen + PLen);
0422 byte *D = buffer, *S = buffer+DLen, *P = buffer+DLen+SLen, *I = S;
0423
0424 if (D)
0425 std::memset(D, purpose, DLen);
0426
0427 size_t i;
0428 for (i=0; i<SLen; i++)
0429 S[i] = salt[i % saltLen];
0430 for (i=0; i<PLen; i++)
0431 P[i] = secret[i % secretLen];
0432
0433 T hash;
0434 SecByteBlock Ai(T::DIGESTSIZE), B(v);
0435 ThreadUserTimer timer;
0436
0437 while (derivedLen > 0)
0438 {
0439 hash.CalculateDigest(Ai, buffer, buffer.size());
0440
0441 if (timeInSeconds)
0442 {
0443 timeInSeconds = timeInSeconds / ((derivedLen + Ai.size() - 1) / Ai.size());
0444 timer.StartTimer();
0445 }
0446
0447 for (i=1; i<iterations || (timeInSeconds && (i%128!=0 || timer.ElapsedTimeAsDouble() < timeInSeconds)); i++)
0448 hash.CalculateDigest(Ai, Ai, Ai.size());
0449
0450 if (timeInSeconds)
0451 {
0452 iterations = (unsigned int)i;
0453 timeInSeconds = 0;
0454 }
0455
0456 for (i=0; i<B.size(); i++)
0457 B[i] = Ai[i % Ai.size()];
0458
0459 Integer B1(B, B.size());
0460 ++B1;
0461 for (i=0; i<ILen; i+=v)
0462 (Integer(I+i, v) + B1).Encode(I+i, v);
0463
0464 #if CRYPTOPP_MSC_VERSION
0465 const size_t segmentLen = STDMIN(derivedLen, Ai.size());
0466 memcpy_s(derived, segmentLen, Ai, segmentLen);
0467 #else
0468 const size_t segmentLen = STDMIN(derivedLen, Ai.size());
0469 std::memcpy(derived, Ai, segmentLen);
0470 #endif
0471
0472 derived += segmentLen;
0473 derivedLen -= segmentLen;
0474 }
0475
0476 return iterations;
0477 }
0478
0479 NAMESPACE_END
0480
0481 #endif