在PKCS5_PBKDF2_HMAC的Crypto ++手册中,有两个DeriveKey的签名。
第一:
size_t DeriveKey (byte *derived, size_t derivedLen, const byte *secret, size_t secretLen, const NameValuePairs ¶ms=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 ¶ms=g_nullNameValuePairs
。
很遗憾,在文档中我找不到使用示例。通常,我的目标是用nullptr salt替换第二个函数的调用,但同时我需要发送unsigned int iterations, double timeInSecond
。
此签名是KeyDerivationFunction
界面的一部分。所有KDF都源自此:
KeyDerivationFunction
选择此签名是因为KDF的本质是获取种子或秘密,并输出派生的密钥材料。其他参数(例如使用率,迭代计数或内存成本)是增值参数。
size_t DeriveKey (byte *derived, size_t derivedLen,
const byte *secret, size_t secretLen,
const NameValuePairs ¶ms=g_nullNameValuePairs) const
允许传递任意参数。这是必需的,因为KDF参数变化很大。例如,PBKDF在其派生中使用单个“使用”八位位组;而Scrypt在推导过程中使用“内存硬度”或“成本”。使用NameValuePairs
,那些可变的参数可以通过恒定接口传递。
NameValuePairs
还提供了一些帮助程序,例如KeyDerivationFunction
,MinDerivedKeyLength
和MaxDerivedKeyLength
。
此签名更加专业。它被保留,因为它存在于Crypto ++的早期。它处理多个旧的KDF,例如IsValidDerivedLength
,P1363_KDF2
,PKCS12_PBKDF
,但无法处理较新的KDF,例如Argon,HKDF和Scrypt。
PKCS5_PBKDF2_HMAC
如果我们要处理现代KDF,则带有更多参数的更新签名将类似于:
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
如您所见,这很快就失控了。
所以我们现在要做的是,使用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
unsigned int iterations,
word64 cost, // Scrypt
word64 blockSize, // Scrypt
word64 parallelization // Scrypt
double timeInSeconds=0 ) const
接口并通过KeyDerivationFunction
传递参数:
NameValuePairs
但是,没有什么可以阻止像Scrypt这样的派生类提供仅接受其确切参数的重载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(), (const byte*)&pass[0], pass.size(), params);
,这就是Scrypt(和其他)KDF所做的。这是Scrypt的重载:
DeriveKey
这是HKDF重载的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
注意,在Crypto ++ 7.0的发行版610下,添加了带有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 ++ Wiki的更多阅读内容: