24#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE
25# if defined(__clang__)
26# pragma GCC diagnostic ignored "-Wtautological-compare"
27# elif defined(__GNUC__)
28# pragma GCC diagnostic ignored "-Wtype-limits"
32ANONYMOUS_NAMESPACE_BEGIN
35using CryptoPP::word32;
36using CryptoPP::word64;
37using CryptoPP::GetWord;
38using CryptoPP::PutWord;
39using CryptoPP::Salsa20_Core;
40using CryptoPP::rotlConstant;
41using CryptoPP::LITTLE_ENDIAN_ORDER;
42using CryptoPP::AlignedSecByteBlock;
44inline void LE32ENC(
byte* out,
word32 in)
46 PutWord(
false, LITTLE_ENDIAN_ORDER, out, in);
49inline word32 LE32DEC(
const byte* in)
51 return GetWord<word32>(
false, LITTLE_ENDIAN_ORDER, in);
54inline word64 LE64DEC(
const byte* in)
56 return GetWord<word64>(
false, LITTLE_ENDIAN_ORDER, in);
59inline void BlockCopy(
byte* dest,
byte* src,
size_t len)
64 for (
size_t i = 0; i < len; ++i)
67 for (
size_t i = 0; i < len; ++i)
72inline void BlockXOR(
byte* dest,
byte* src,
size_t len)
77 for (
size_t i = 0; i < len; ++i)
80 for (
size_t i = 0; i < len; ++i)
85inline void PBKDF2_SHA256(
byte* buf,
size_t dkLen,
86 const byte* passwd,
size_t passwdlen,
87 const byte* salt,
size_t saltlen,
byte count)
89 using CryptoPP::SHA256;
90 using CryptoPP::PKCS5_PBKDF2_HMAC;
93 pbkdf.
DeriveKey(buf, dkLen, 0, passwd, passwdlen, salt, saltlen, count, 0.0f);
96inline void Salsa20_8(
byte B[64])
100 for (
size_t i = 0; i < 16; ++i)
101 B32[i] = LE32DEC(&B[i * 4]);
103 Salsa20_Core(B32, 8);
105 for (
size_t i = 0; i < 16; ++i)
106 LE32ENC(&B[4 * i], B32[i]);
109inline void BlockMix(
byte* B,
byte* Y,
size_t r)
114 BlockCopy(X, &B[(2 * r - 1) * 64], 64);
117 for (
size_t i = 0; i < 2 * r; ++i)
120 BlockXOR(X, &B[i * 64], 64);
124 BlockCopy(&Y[i * 64], X, 64);
128 for (
size_t i = 0; i < r; ++i)
129 BlockCopy(&B[i * 64], &Y[(i * 2) * 64], 64);
131 for (
size_t i = 0; i < r; ++i)
132 BlockCopy(&B[(i + r) * 64], &Y[(i * 2 + 1) * 64], 64);
135inline word64 Integerify(
byte* B,
size_t r)
137 byte* X = &B[(2 * r - 1) * 64];
141inline void Smix(
byte* B,
size_t r, word64 N,
byte* V,
byte* XY)
147 BlockCopy(X, B, 128 * r);
150 for (word64 i = 0; i < N; ++i)
153 BlockCopy(&V[i * (128 * r)], X, 128 * r);
160 for (word64 i = 0; i < N; ++i)
163 word64 j = Integerify(X, r) & (N - 1);
166 BlockXOR(X, &V[j * (128 * r)], 128 * r);
171 BlockCopy(B, X, 128 * r);
174ANONYMOUS_NAMESPACE_END
176NAMESPACE_BEGIN(CryptoPP)
178size_t
Scrypt::GetValidDerivedLength(
size_t keylength)
const
180 if (keylength > MaxDerivedKeyLength())
181 return MaxDerivedKeyLength();
185void Scrypt::ValidateParameters(
size_t derivedLen, word64 cost, word64 blockSize, word64 parallelization)
const
188 CRYPTOPP_ASSERT(derivedLen != 0);
189 CRYPTOPP_ASSERT(cost != 0);
190 CRYPTOPP_ASSERT(blockSize != 0);
191 CRYPTOPP_ASSERT(parallelization != 0);
199 if (parallelization == 0)
203 if (std::numeric_limits<size_t>::max() > std::numeric_limits<word32>::max())
205 const word64 maxLen = ((
static_cast<word64
>(1) << 32) - 1) * 32;
206 if (derivedLen > maxLen) {
207 std::ostringstream oss;
208 oss <<
"derivedLen " << derivedLen <<
" is larger than " << maxLen;
214 CRYPTOPP_ASSERT(parallelization <=
static_cast<word64
>(std::numeric_limits<int>::max()));
215 if (parallelization >
static_cast<word64
>(std::numeric_limits<int>::max()))
217 std::ostringstream oss;
218 oss <<
" parallelization " << parallelization <<
" is larger than ";
219 oss << std::numeric_limits<int>::max();
227 const word64 prod =
static_cast<word64
>(blockSize) * parallelization;
228 CRYPTOPP_ASSERT(prod < (1U << 30));
230 if (prod >= (1U << 30)) {
231 std::ostringstream oss;
232 oss <<
"r*p " << prod <<
" is larger than " << (1U << 30);
242#if defined(CRYPTOPP_WORD128_AVAILABLE)
243 const word128 maxElems =
static_cast<word128
>(SIZE_MAX);
244 bool bLimit = (maxElems >=
static_cast<word128
>(cost) * blockSize * 128U);
245 bool xyLimit = (maxElems >=
static_cast<word128
>(parallelization) * blockSize * 128U);
246 bool vLimit = (maxElems >=
static_cast<word128
>(blockSize) * 256U + 64U);
248 const word64 maxElems =
static_cast<word64
>(SIZE_MAX);
249 bool bLimit = (blockSize < maxElems / 128U / cost);
250 bool xyLimit = (blockSize < maxElems / 128U / parallelization);
251 bool vLimit = (blockSize < (maxElems - 64U) / 256U);
254 CRYPTOPP_ASSERT(bLimit); CRYPTOPP_ASSERT(xyLimit); CRYPTOPP_ASSERT(vLimit);
255 if (!bLimit || !xyLimit || !vLimit)
256 throw std::bad_alloc();
260 const byte*secret,
size_t secretLen,
const NameValuePairs& params)
const
262 CRYPTOPP_ASSERT(secret );
263 CRYPTOPP_ASSERT(derived && derivedLen);
266 word64 cost=0, blockSize=0, parallelization=0;
267 if(params.
GetValue(
"Cost", cost) ==
false)
270 if(params.
GetValue(
"BlockSize", blockSize) ==
false)
271 blockSize = defaultBlockSize;
273 if(params.
GetValue(
"Parallelization", parallelization) ==
false)
274 parallelization = defaultParallelization;
277 (void)params.
GetValue(
"Salt", salt);
279 return DeriveKey(derived, derivedLen, secret, secretLen, salt.
begin(), salt.
size(), cost, blockSize, parallelization);
283 const byte*salt,
size_t saltLen, word64 cost, word64 blockSize, word64 parallel)
const
285 CRYPTOPP_ASSERT(secret );
286 CRYPTOPP_ASSERT(derived && derivedLen);
290 ValidateParameters(derivedLen, cost, blockSize, parallel);
295 PBKDF2_SHA256(B, B.
size(), secret, secretLen, salt, saltLen, 1);
300 maxParallel = std::numeric_limits<int>::max();
303 int threads =
STDMIN(omp_get_max_threads(), maxParallel);
307 #pragma omp parallel num_threads(threads)
315 for (
int i = 0; i < maxParallel; ++i)
318 const ptrdiff_t offset =
static_cast<ptrdiff_t
>(blockSize*i*128);
319 Smix(B+offset,
static_cast<size_t>(blockSize), cost, V, XY);
324 PBKDF2_SHA256(derived, derivedLen, secret, secretLen, B, B.
size(), 1);
Classes for working with NameValuePairs.
Standard names for retrieving values by name when working with NameValuePairs.
Used to pass byte array input as part of a NameValuePairs object.
const byte * begin() const
Pointer to the first byte in the memory block.
size_t size() const
Length of the memory block.
An invalid argument was detected.
void ThrowIfInvalidDerivedKeyLength(size_t length) const
Validates the derived key length.
Interface for retrieving values given their names.
bool GetValue(const char *name, T &value) const
Get a named value.
size_t DeriveKey(byte *derived, size_t derivedLen, const byte *secret, size_t secretLen, const NameValuePairs ¶ms=g_nullNameValuePairs) const
Derive a key from a seed.
Scrypt key derivation function.
size_t DeriveKey(byte *derived, size_t derivedLen, const byte *secret, size_t secretLen, const NameValuePairs ¶ms) const
Derive a key from a seed.
size_t MaxDerivedKeyLength() const
Determine maximum number of bytes.
size_type size() const
Provides the count of elements in the SecBlock.
unsigned int word32
32-bit unsigned datatype
Utility functions for the Crypto++ library.
void PutWord(bool assumeAligned, ByteOrder order, byte *block, T value, const byte *xorBlock=NULLPTR)
Access a block of memory.
bool IsPowerOf2(const T &value)
Tests whether a value is a power of 2.
const T & STDMIN(const T &a, const T &b)
Replacement function for std::min.
bool SafeConvert(T1 from, T2 &to)
Tests whether a conversion from -> to is safe to perform.
Password based key derivation functions.
Classes for Salsa and Salsa20 stream ciphers.
Classes for Scrypt from RFC 7914.
Classes for SHA-1 and SHA-2 family of message digests.