EVP_KDF-ARGON2
名称
EVP_KDF-ARGON2 - Argon2 EVP KDF 实现
描述
支持通过 EVP_KDF API 计算 argon2 基于密码的 KDF。
EVP_KDF-ARGON2 算法实现了 Argon2 基于密码的密钥推导函数,如 IETF RFC 9106 中所述。它在内存方面是困难的,因为它有意地需要大量的 RAM 才能进行高效的计算。这样做的目的是为了使对缺乏大量主内存(如 GPU 或 ASIC)的系统上的密码进行暴力破解在计算上不可行。
Argon2d(Argon2i)使用数据相关(数据无关)内存访问和主要搜索来解决权衡(侧信道)攻击。
Argon2id 是一种混合结构,它在前两次切片的第一轮中以数据无关的方式生成参考地址,如 Argon2i 中一样,而在后面的切片和下一轮中以数据相关的方式生成,如 Argon2d 中一样。
不支持 Sbox 强化版本的 Argon2ds。
有关更多信息,请参阅 RFC 9106。
支持的参数
支持的参数是
- "pass" (OSSL_KDF_PARAM_PASSWORD) <八位字节串>
- "salt" (OSSL_KDF_PARAM_SALT) <八位字节串>
- "secret" (OSSL_KDF_PARAM_SECRET) <八位字节串>
- "iter" (OSSL_KDF_PARAM_ITER) <无符号整数>
- "size" (OSSL_KDF_PARAM_SIZE) <无符号整数>
-
这些参数的用法如 "PARAMETERS" in EVP_KDF(3) 中所述。
请注意,RFC 9106 针对大多数应用建议使用 128 位盐,或者在空间限制的情况下使用 64 位盐。建议至少使用 128 位输出长度。
请注意,密钥(或胡椒粉)是与密码一起使用的可选秘密数据。
- "threads" (OSSL_KDF_PARAM_THREADS) <无符号整数>
-
线程数量,上限为车道数量。
这只能与内置线程支持一起使用。必须显式启用多线程。有关更多信息,请参阅示例部分。
- "ad" (OSSL_KDF_PARAM_ARGON2_AD) <八位字节串>
-
可选的关联数据,可用于“标记”一组密钥,或将它们绑定到特定公钥,而无需修改盐。
- "lanes" (OSSL_KDF_PARAM_ARGON2_LANES) <无符号整数>
-
Argon2 将请求的内存大小划分为车道,每个车道旨在并行处理。例如,在具有 p 个内核的系统上,建议使用 p 个车道。
车道数量用于推导出密钥。可以指定比可用计算线程数量更多的车道。如果禁用多线程,尤其鼓励这样做。
- "memcost" (OSSL_KDF_PARAM_ARGON2_MEMCOST) <无符号整数>
-
内存成本参数(使用的 1k 内存块数量)。
- "version" (OSSL_KDF_PARAM_ARGON2_VERSION) <无符号整数>
-
Argon2 版本。支持的值:0x10、0x13(默认)。
- "early_clean" (OSSL_KDF_PARAM_EARLY_CLEAN) <无符号整数>
-
如果设置(非零),则存储在 Argon2 上下文中的密码和密钥将在初始哈希计算期间尽早归零,只要它们不再需要。否则,它们将在清理、释放、重置时与 Argon2 上下文数据的其余部分一起归零。
例如,这在需要从单个密码和密钥生成具有不同 ad 值的多个密钥时非常有用。
示例
此示例使用 Argon2d,密码为“1234567890”,盐为“saltsalt”,使用 2 个车道、2 个线程,内存成本为 65536
#include <string.h> /* strlen */
#include <openssl/core_names.h> /* OSSL_KDF_* */
#include <openssl/params.h> /* OSSL_PARAM_* */
#include <openssl/thread.h> /* OSSL_set_max_threads */
#include <openssl/kdf.h> /* EVP_KDF_* */
int main(void)
{
int retval = 1;
EVP_KDF *kdf = NULL;
EVP_KDF_CTX *kctx = NULL;
OSSL_PARAM params[6], *p = params;
/* argon2 params, please refer to RFC9106 for recommended defaults */
uint32_t lanes = 2, threads = 2, memcost = 65536;
char pwd[] = "1234567890", salt[] = "saltsalt";
/* derive result */
size_t outlen = 128;
unsigned char result[outlen];
/* required if threads > 1 */
if (OSSL_set_max_threads(NULL, threads) != 1)
goto fail;
p = params;
*p++ = OSSL_PARAM_construct_uint32(OSSL_KDF_PARAM_THREADS, &threads);
*p++ = OSSL_PARAM_construct_uint32(OSSL_KDF_PARAM_ARGON2_LANES,
&lanes);
*p++ = OSSL_PARAM_construct_uint32(OSSL_KDF_PARAM_ARGON2_MEMCOST,
&memcost);
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT,
salt,
strlen((const char *)salt));
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_PASSWORD,
pwd,
strlen((const char *)pwd));
*p++ = OSSL_PARAM_construct_end();
if ((kdf = EVP_KDF_fetch(NULL, "ARGON2D", NULL)) == NULL)
goto fail;
if ((kctx = EVP_KDF_CTX_new(kdf)) == NULL)
goto fail;
if (EVP_KDF_derive(kctx, &result[0], outlen, params) != 1)
goto fail;
printf("Output = %s\n", OPENSSL_buf2hexstr(result, outlen));
retval = 0;
fail:
EVP_KDF_free(kdf);
EVP_KDF_CTX_free(kctx);
OSSL_set_max_threads(NULL, 0);
return retval;
}
注释
"ARGON2I"、"ARGON2D" 和 "ARGON2ID" 是此实现的名称;它可以与 EVP_KDF_fetch() 函数一起使用。
符合
RFC 9106 Argon2,请参阅 https://www.rfc-editor.org/rfc/rfc9106.txt.
另请参阅
EVP_KDF(3), EVP_KDF_CTX_new(3), EVP_KDF_CTX_free(3), EVP_KDF_CTX_set_params(3), EVP_KDF_derive(3), "PARAMETERS" in EVP_KDF(3)
历史
此功能已添加到 OpenSSL 3.2 中。
版权
版权所有 2022-2023 OpenSSL 项目作者。保留所有权利。
根据 Apache 许可证 2.0(“许可证”)授权。除符合许可证的规定外,您不得使用此文件。您可以在源代码分发中的 LICENSE 文件或 https://www.openssl.org/source/license.html 中获取副本。