OpenSSL

密码学和SSL/TLS工具包

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