OpenSSL

密码学和SSL/TLS工具包

EVP_PKEY-DHX

名称

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

描述

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

有关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-56Ar3FFC完全公钥验证

对于DH密钥,EVP_PKEY_public_check_quick(3)在DH密钥为已批准的命名安全素数组时符合SP800-56Ar3FFC部分公钥验证,否则与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中获取副本。