EVP_KDF-SCRYPT
名称
EVP_KDF-SCRYPT - scrypt EVP_KDF 实现
描述
通过EVP_KDF API 支持计算scrypt 基于密码的密钥派生函数。
EVP_KDF-SCRYPT 算法实现了 scrypt 基于密码的密钥派生函数,如 RFC 7914 中所述。它在内存方面是困难的,因为它故意需要大量的 RAM 才能进行高效计算。这样做的目的是使在缺乏大量主内存(如 GPU 或 ASIC)的系统上对密码进行暴力破解在计算上不可行。
scrypt 提供了三个可以自定义的工作因子:N、r 和 p。N 必须是 2 的正整数次幂,是通用工作因子,并以近似线性的方式扩展 CPU 时间。r 是内部使用的哈希函数的块大小,p 是并行因子。r 和 p 都需要大于零。scrypt 计算所需的 RAM 量大约为 (128 * N * r * p) 字节。
在 Colin Percival 的原始论文(“通过顺序内存困难函数增强密钥派生”,2009 年)中,建议的值在 2.5 GHz 英特尔酷睿 2 Duo 上的计算时间小于 5 秒,N = 2^20 = 1048576、r = 8、p = 1。因此,此计算所需的内存量约为 1 GiB。在更新的 CPU(3.5 GHz 英特尔 i7-5930K)上,此计算大约需要 3 秒。当未指定 N、r 或 p 时,它们分别默认为 1048576、8 和 1。scrypt 使用的最大 RAM 量默认为 1025 MiB。
标识
"SCRYPT" 是此实现的名称;它可以与 EVP_KDF_fetch() 函数一起使用。
支持的参数
支持的参数为:
- "pass" (OSSL_KDF_PARAM_PASSWORD) <八位字节串>
- "salt" (OSSL_KDF_PARAM_SALT) <八位字节串>
-
这些参数的工作方式如 "EVP_KDF(3) 中的参数" 中所述。
- "n" (OSSL_KDF_PARAM_SCRYPT_N) <无符号整数>
- "r" (OSSL_KDF_PARAM_SCRYPT_R) <无符号整数>
- "p" (OSSL_KDF_PARAM_SCRYPT_P) <无符号整数>
- "maxmem_bytes" (OSSL_KDF_PARAM_SCRYPT_MAXMEM) <无符号整数>
-
这些参数配置 scrypt 工作因子 N、r、maxmem 和 p。N 和 maxmem_bytes 都是 uint64_t 类型的参数。r 和 p 都是 uint32_t 类型的参数。
- "properties" (OSSL_KDF_PARAM_PROPERTIES) <UTF8 字符串>
-
这可用于在内部获取固定摘要时设置属性查询字符串。如果未设置此值,则使用 NULL。
注释
可以通过调用以下命令获取 scrypt 的上下文:
EVP_KDF *kdf = EVP_KDF_fetch(NULL, "SCRYPT", NULL);
EVP_KDF_CTX *kctx = EVP_KDF_CTX_new(kdf);
scrypt 密钥派生的输出长度通过 EVP_KDF_derive(3) 函数的 "keylen" 参数指定。
示例
此示例使用密码 "password"、盐 "NaCl" 和 N = 1024、r = 8、p = 16 使用 scrypt 派生 64 字节长的测试向量。
EVP_KDF *kdf;
EVP_KDF_CTX *kctx;
unsigned char out[64];
OSSL_PARAM params[6], *p = params;
kdf = EVP_KDF_fetch(NULL, "SCRYPT", NULL);
kctx = EVP_KDF_CTX_new(kdf);
EVP_KDF_free(kdf);
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_PASSWORD,
"password", (size_t)8);
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT,
"NaCl", (size_t)4);
*p++ = OSSL_PARAM_construct_uint64(OSSL_KDF_PARAM_SCRYPT_N, (uint64_t)1024);
*p++ = OSSL_PARAM_construct_uint32(OSSL_KDF_PARAM_SCRYPT_R, (uint32_t)8);
*p++ = OSSL_PARAM_construct_uint32(OSSL_KDF_PARAM_SCRYPT_P, (uint32_t)16);
*p = OSSL_PARAM_construct_end();
if (EVP_KDF_derive(kctx, out, sizeof(out), params) <= 0) {
error("EVP_KDF_derive");
}
{
const unsigned char expected[sizeof(out)] = {
0xfd, 0xba, 0xbe, 0x1c, 0x9d, 0x34, 0x72, 0x00,
0x78, 0x56, 0xe7, 0x19, 0x0d, 0x01, 0xe9, 0xfe,
0x7c, 0x6a, 0xd7, 0xcb, 0xc8, 0x23, 0x78, 0x30,
0xe7, 0x73, 0x76, 0x63, 0x4b, 0x37, 0x31, 0x62,
0x2e, 0xaf, 0x30, 0xd9, 0x2e, 0x22, 0xa3, 0x88,
0x6f, 0xf1, 0x09, 0x27, 0x9d, 0x98, 0x30, 0xda,
0xc7, 0x27, 0xaf, 0xb9, 0x4a, 0x83, 0xee, 0x6d,
0x83, 0x60, 0xcb, 0xdf, 0xa2, 0xcc, 0x06, 0x40
};
assert(!memcmp(out, expected, sizeof(out)));
}
EVP_KDF_CTX_free(kctx);
符合标准
RFC 7914
参见
EVP_KDF(3)、EVP_KDF_CTX_new(3)、EVP_KDF_CTX_free(3)、EVP_KDF_CTX_set_params(3)、EVP_KDF_derive(3)、"EVP_KDF(3) 中的参数"
历史
此功能在 OpenSSL 3.0 中添加。
版权
版权所有 2017-2021 OpenSSL 项目作者。保留所有权利。
根据 Apache 许可证 2.0(“许可证”)授权。除非符合许可证,否则您不得使用此文件。您可以在源代码分发中的 LICENSE 文件或 https://www.openssl.org/source/license.html 中获取副本。