Причина подписи класса Crypto ++ PKCS5_PBKDF2_HMAC? - PullRequest
1 голос
/ 17 октября 2019

В руководстве Crypto ++ для PKCS5_PBKDF2_HMAC есть две подписи DeriveKey.

Первая:

size_t  DeriveKey (byte *derived, size_t derivedLen, const byte *secret, size_t secretLen, const NameValuePairs &params=g_nullNameValuePairs) const

Вторая:

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

Я хотел бы понять назначение последнего параметра в первой подписи. NameValuePairs &params=g_nullNameValuePairs.

К сожалению, в документации я не нашел пример использования. Как правило, моя цель - заменить вызовы второй функции солями nullptr первым, но в то же время мне нужно отправить unsigned int iterations, double timeInSecond.

1 Ответ

0 голосов
/ 18 октября 2019

Для вашего первого случая эта подпись является частью интерфейса KeyDerivationFunction. Почти все KDF происходят из этого. Единственный KDF, который не является производным от него, это P1363_KDF2, который используется в качестве функции генерации маски в схемах заполнения.

size_t  DeriveKey (byte *derived, size_t derivedLen,
                   const byte *secret, size_t secretLen,
                   const NameValuePairs &params=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 ++:

...