OpenSSL

密码学与 SSL/TLS 工具包

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 中获取副本。