OpenSSL

密码学和SSL/TLS工具包

EVP_KEYMGMT-DH

名称

EVP_PKEY-DH, EVP_PKEY-DHX, EVP_KEYMGMT-DH, EVP_KEYMGMT-DHX - EVP_PKEY DH 和 DHX 密钥类型及算法支持

描述

对于DH FFC 密钥协商,可以使用两类域参数:“安全”域参数,与批准的命名安全素数组相关联;以及一类“FIPS186-type”域参数。FIPS186-type 域参数仅应用于与无法升级以使用批准的安全素数组的现有应用程序的向后兼容性。

有关 FFC 密钥的更多信息,请参阅 EVP_PKEY-FFC(7)

DH 密钥类型使用 PKCS#3 格式,该格式保存pg,但不保存q 值。DHX 密钥类型使用 X9.42 格式,该格式保存q 的值,这必须用于 FIPS186-4。如果需要密钥验证,用户应注意与 FIPS186-4 样式参数相关的细微差别,如 “DH 密钥验证” 中所述。

DH 和 DHX 域参数

除了所有 FFC 密钥类型都应支持的通用 FCC 参数(请参阅 EVP_PKEY-FFC(7) 中的“FFC 参数”)之外,DHXDH 密钥类型实现还支持以下内容

"group" (OSSL_PKEY_PARAM_GROUP_NAME) <UTF8 字符串>

设置或获取一个字符串,该字符串将DHDHX 命名安全素数组与pqg 的已知值相关联。

OpenSSL 的默认提供程序和 FIPS 提供程序可以使用以下值:“ffdhe2048”、“ffdhe3072”、“ffdhe4096”、“ffdhe6144”、“ffdhe8192”、“modp_2048”、“modp_3072”、“modp_4096”、“modp_6144”、“modp_8192”。

OpenSSL 的默认提供程序还可以使用以下附加值:“modp_1536”、“dh_1024_160”、“dh_2048_224”、“dh_2048_256”。

DH/DHX 命名组可以轻松验证,因为参数是众所周知的。对于仅传输pg 的协议,还可以检索q 的值。

DH 和 DHX 附加参数

"encoded-pub-key" (OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY) <八位字节字符串>

用于获取和设置 TLS 协议密钥交换消息中使用的 DH 公钥的编码。请参阅 EVP_PKEY_set1_encoded_public_key() 和 EVP_PKEY_get1_encoded_public_key()。

DH 附加域参数

"safeprime-generator" (OSSL_PKEY_PARAM_DH_GENERATOR) <整数>

用于使用旧的安全素数生成器代码生成 DH 安全素数。默认值为 2。如果需要域参数验证,建议改为使用命名安全素数组。

FIPS 不允许随机生成的安全素数,因此对于 OpenSSL FIPS 提供程序设置此值将改为根据p 的大小选择一个命名安全素数组。

DH 和 DHX 域参数/密钥生成参数

除了所有 FFC 密钥类型都应支持的通用 FFC 密钥生成参数(请参阅 EVP_PKEY-FFC(7) 中的“FFC 密钥生成参数”)之外,DHDHX 密钥类型实现还支持以下内容

"type" (OSSL_PKEY_PARAM_FFC_TYPE) <UTF8 字符串>

设置参数生成的类型。对于DH,有效值为

"fips186_4"
"default"
"fips186_2"

这些在 EVP_PKEY-FFC(7) 中的“FFC 密钥生成参数” 中进行了描述

"group"

这指定将使用“pbits”类型选择命名安全素数名称。

"generator"

安全素数生成器。请参阅上面的“safeprime-generator”类型。这仅对DH 密钥有效。

"pbits" (OSSL_PKEY_PARAM_FFC_PBITS) <无符号整数>

设置素数“p”的大小(以位为单位)。

对于“fips186_4”,这必须为 2048。对于“fips186_2”,这必须为 1024。对于“group”,这可以是 2048、3072、4096、6144 或 8192 中的任何一个。

"priv_len" (OSSL_PKEY_PARAM_DH_PRIV_LEN) <整数>

一个可选值,用于设置生成的私钥的最大长度。如果未设置此值,则使用默认值,即 BN_num_bits(q)) 的最大值。这可以设置为的最小值为 2 * s。其中 s 是密钥的安全强度,对于密钥大小为 2048、3072、4096、6144 和 8192,其值分别为 112、128、152、176 和 200。

DH 密钥验证

对于不是命名组的DHX,FIPS186-4 标准指定用于 FFC 参数生成的数值也需要用于参数验证。这意味着可能需要存储seedpcountergindexhindex 的可选 FFC 域参数值以用于验证目的。对于DHXseedpcounter 可以存储在 ASN1 数据中(但gindexhindex 无法存储)。建议改为使用命名安全素数组。

对于 DH 密钥,EVP_PKEY_param_check(3) 的行为方式如下:OpenSSL FIPS 提供程序测试参数是否为批准的安全素数组或 FFC 参数是否符合 SP800-56Ar3 域参数有效性的保证中定义的 FIPS186-4。OpenSSL 默认提供程序使用更简单的检查,允许出于向后兼容性目的没有q 值。

对于 DH 密钥,EVP_PKEY_param_check_quick(3) 等效于 EVP_PKEY_param_check(3)

对于 DH 密钥,EVP_PKEY_public_check(3) 符合 SP800-56Ar3 FFC 完全公钥验证

对于 DH 密钥,EVP_PKEY_public_check_quick(3) 在 DH 密钥是批准的命名安全素数组时符合 SP800-56Ar3 FFC 部分公钥验证,否则与 EVP_PKEY_public_check(3) 相同。

对于 DH 密钥,EVP_PKEY_private_check(3) 测试私钥是否在根据 SP800-56Ar3 的正确范围内。OpenSSL FIPS 提供程序要求设置q 的值(请注意,这对于命名安全素数组是设置的)。为了向后兼容性,OpenSSL 默认提供程序仅要求设置p

对于 DH 密钥,EVP_PKEY_pairwise_check(3) 符合 SP800-56Ar3 所有者对成对一致性的保证

示例

可以通过调用以下方法获取EVP_PKEY 上下文

EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_from_name(NULL, "DH", NULL);

可以通过调用以下方法使用命名安全素数组生成DH 密钥

int priv_len = 2 * 112;
OSSL_PARAM params[3];
EVP_PKEY *pkey = NULL;
EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_from_name(NULL, "DH", NULL);

params[0] = OSSL_PARAM_construct_utf8_string("group", "ffdhe2048", 0);
/* "priv_len" is optional */
params[1] = OSSL_PARAM_construct_int("priv_len", &priv_len);
params[2] = OSSL_PARAM_construct_end();

EVP_PKEY_keygen_init(pctx);
EVP_PKEY_CTX_set_params(pctx, params);
EVP_PKEY_generate(pctx, &pkey);
...
EVP_PKEY_free(pkey);
EVP_PKEY_CTX_free(pctx);

可以通过调用以下方法根据FIPS186-4 生成DHX 域参数

int gindex = 2;
unsigned int pbits = 2048;
unsigned int qbits = 256;
OSSL_PARAM params[6];
EVP_PKEY *param_key = NULL;
EVP_PKEY_CTX *pctx = NULL;

pctx = EVP_PKEY_CTX_new_from_name(NULL, "DHX", NULL);
EVP_PKEY_paramgen_init(pctx);

params[0] = OSSL_PARAM_construct_uint("pbits", &pbits);
params[1] = OSSL_PARAM_construct_uint("qbits", &qbits);
params[2] = OSSL_PARAM_construct_int("gindex", &gindex);
params[3] = OSSL_PARAM_construct_utf8_string("type", "fips186_4", 0);
params[4] = OSSL_PARAM_construct_utf8_string("digest", "SHA256", 0);
params[5] = OSSL_PARAM_construct_end();
EVP_PKEY_CTX_set_params(pctx, params);

EVP_PKEY_generate(pctx, &param_key);

EVP_PKEY_print_params(bio_out, param_key, 0, NULL);
...
EVP_PKEY_free(param_key);
EVP_PKEY_CTX_free(pctx);

可以通过调用以下方法使用域参数生成DH 密钥

EVP_PKEY *key = NULL;
EVP_PKEY_CTX *gctx = EVP_PKEY_CTX_new_from_pkey(NULL, param_key, NULL);

EVP_PKEY_keygen_init(gctx);
EVP_PKEY_generate(gctx, &key);
EVP_PKEY_print_private(bio_out, key, 0, NULL);
...
EVP_PKEY_free(key);
EVP_PKEY_CTX_free(gctx);

要验证从PEMDER 数据解码的FIPS186-4 DHX 域参数,可能需要将生成过程中使用的附加值设置到密钥中。

EVP_PKEY_todata()、OSSL_PARAM_merge() 和 EVP_PKEY_fromdata() 可用于在实际验证之前将这些参数添加到原始密钥或域参数中。在生产代码中,应检查返回值。

EVP_PKEY *received_domp = ...; /* parameters received and decoded */
unsigned char *seed = ...;     /* and additional parameters received */
size_t seedlen = ...;          /* by other means, required */
int gindex = ...;              /* for the validation */
int pcounter = ...;
int hindex = ...;
OSSL_PARAM extra_params[4];
OSSL_PARAM *domain_params = NULL;
OSSL_PARAM *merged_params = NULL;
EVP_PKEY_CTX *ctx = NULL, *validate_ctx = NULL;
EVP_PKEY *complete_domp = NULL;

EVP_PKEY_todata(received_domp, OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS,
                &domain_params);
extra_params[0] = OSSL_PARAM_construct_octet_string("seed", seed, seedlen);
/*
 * NOTE: For unverifiable g use "hindex" instead of "gindex"
 * extra_params[1] = OSSL_PARAM_construct_int("hindex", &hindex);
 */
extra_params[1] = OSSL_PARAM_construct_int("gindex", &gindex);
extra_params[2] = OSSL_PARAM_construct_int("pcounter", &pcounter);
extra_params[3] = OSSL_PARAM_construct_end();
merged_params = OSSL_PARAM_merge(domain_params, extra_params);

ctx = EVP_PKEY_CTX_new_from_name(NULL, "DHX", NULL);
EVP_PKEY_fromdata_init(ctx);
EVP_PKEY_fromdata(ctx, &complete_domp, OSSL_KEYMGMT_SELECT_ALL,
                  merged_params);

validate_ctx = EVP_PKEY_CTX_new_from_pkey(NULL, complete_domp, NULL);
if (EVP_PKEY_param_check(validate_ctx) > 0)
    /* validation_passed(); */
else
    /* validation_failed(); */

OSSL_PARAM_free(domain_params);
OSSL_PARAM_free(merged_params);
EVP_PKEY_CTX_free(ctx);
EVP_PKEY_CTX_free(validate_ctx);
EVP_PKEY_free(complete_domp);

符合

RFC 7919(TLS ffdhe 命名安全素数组)
RFC 3526(IKE modp 命名安全素数组)
RFC 5114(“dh_1024_160”、“dh_2048_224”和“dh_2048_256”的附加 DH 命名组)。

SP800-56Ar3 的以下部分

5.5.1.1 FFC 域参数选择/生成
附录 D:FFC 安全素数组

FIPS186-4 的以下部分

A.1.1.2 使用批准的哈希函数生成可能的素数 p 和 q。
A.2.3 生成规范生成器 g。
A.2.1 生成器 g 的不可验证生成。

另请参阅

EVP_PKEY-FFC(7)EVP_KEYEXCH-DH(7) EVP_PKEY(3)provider-keymgmt(7)EVP_KEYMGMT(3)OSSL_PROVIDER-default(7)OSSL_PROVIDER-FIPS(7)

版权所有 2020-2021 OpenSSL 项目作者。保留所有权利。

根据 Apache 许可证 2.0(“许可证”)许可。除非符合许可证,否则您不得使用此文件。您可以在源代码分发中的 LICENSE 文件或 https://www.openssl.org/source/license.html 中获取副本。