Для вашего первого случая эта подпись является частью интерфейса KeyDerivationFunction
. Почти все KDF происходят из этого. Единственный KDF, который не является производным от него, это P1363_KDF2
, который используется в качестве функции генерации маски в схемах заполнения.
size_t DeriveKey (byte *derived, size_t derivedLen,
const byte *secret, size_t secretLen,
const NameValuePairs ¶ms=g_nullNameValuePairs) const
Эта сигнатура была выбрана, потому что суть KDF состоит в том, чтобы взять начальное числоили секрет, и вывод производного ключевого материала. Другие параметры, такие как использование, количество итераций или стоимость памяти, являются дополнительными параметрами.
NameValuePairs
позволяет передавать произвольные параметры. Это необходимо, потому что параметры KDF сильно различаются. Например, ранние PBKDF часто используют один октет «использования» и «счетчик итераций» при выводе;в то время как Scrypt использует «жесткость памяти» или «стоимость» при выводе. С NameValuePairs
эти переменные параметры могут передаваться через согласованный интерфейс.
Класс KeyDerivationFunction
также предоставляет несколько помощников, таких как MinDerivedKeyLength
, MaxDerivedKeyLength
, GetValidDerivedLength
и IsValidDerivedLength
. GetValidDerivedLength
- это виртуальная функция, и все производные классы должны ее реализовывать.
Для вашего второго случая эта сигнатура более специализирована. Он сохраняется, потому что он присутствовал в первые дни Crypto ++. Он обрабатывает несколько старых KDF, таких как P1363_KDF2
, PKCS12_PBKDF
, PKCS5_PBKDF2_HMAC
, но не может обрабатывать более новые KDF, такие как Argon, HKDF и Scrypt.
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
Если мы хотим обрабатывать современные KDF, тоболее новая подпись с большим количеством параметров будет выглядеть примерно так:
size_t DeriveKey (byte *derived, size_t derivedLen,
byte purpose,
const byte *secret, size_t secretLen,
const byte *salt, size_t saltLen,
const byte *pepper, size_t pepperLen, // additional data
const byte *info, size_t infoLen, // additional data
word32 iterations,
word32 version, // Argon2
word32 type, // Argon2
word32 rho, // Argon2
word64 memsize, // Argon2
word64 cost, // Scrypt
word64 blockSize, // Scrypt
word64 parallelization // Scrypt
double timeInSeconds=0 ) const
Как вы можете видеть, это быстро выходит из-под контроля.
Итак, что мы сейчас делаем, используем KeyDerivationFunction
интерфейс и передача параметров через NameValuePairs
:
std::string pass("password"), salt("NaCl");
word64 cost=1024, blockSize=8, parallelization=16;
AlgorithmParameters params = MakeParameters("Cost", cost)
("BlockSize", blockSize)("Parallelization", parallelization)
("Salt", ConstByteArrayParameter((const byte*)&salt[0], salt.size()));
SecByteBlock derived(64);
scrypt.DeriveKey(derived, derived.size(), ConstBytePtr(pass), BytePtrSize(pass), params);
Однако ничто не запрещает производному классу, такому как HKDF или Scrypt, предоставлять перегруженный DeriveKey
, который принимает только его точные параметры, и это то, что HKDF,Scrypt и другие KDF делают.
Вот перегрузка Scrypt. Это точные параметры, используемые в DeriveKey
:
size_t DeriveKey (byte *derived, size_t derivedLen,
const byte *secret, size_t secretLen,
const byte *salt, size_t saltLen,
word64 cost=2, word64 blockSize=8,
word64 parallelization=1) const
А вот перегруженный HKDF DeriveKey
. Вот точные параметры, использованные в его функции деривации:
size_t DeriveKey (byte *derived, size_t derivedLen,
const byte *secret, size_t secretLen,
const byte *salt, size_t saltLen,
const byte *info, size_t infoLen) const
Обратите внимание, что новый интерфейс KeyDerivationFunction
с NameValuePair
был добавлен в Crypto ++ 6.2 в выпуске 610:
Вот еще некоторые чтения из вики Crypto ++: