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 類型」網域參數。FIPS186 類型網域參數僅應使用於與無法升級為使用核准安全質數群組的現有應用程式進行向下相容性。

請參閱 EVP_PKEY-FFC(7) 以取得有關 FFC 金鑰的更多資訊。

DH 金鑰類型使用 PKCS#3 格式,會儲存 pg,但不會儲存 q 值。DHX 金鑰類型使用 X9.42 格式,會儲存 q 值,且必須用於 FIPS186-4。如果需要金鑰驗證,使用者應注意與 FIPS186-4 樣式參數相關的細微差別,如 「DH 金鑰驗證」 中所述。

DH 和 DHX 網域參數

除了所有 FFC 金鑰類型都應支援的常見 FCC 參數(請參閱 EVP_PKEY-FFC(7) 中的「FFC 參數」)之外,DHXDH 金鑰類型實作還支援下列內容

「群組」(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 其他參數

「編碼公鑰」(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY) <八位元組字串>

用於取得和設定 TLS 通訊協定中金鑰交換訊息中使用的 DH 公鑰編碼。請參閱 EVP_PKEY_set1_encoded_public_key() 和 EVP_PKEY_get1_encoded_public_key()。

DH 其他網域參數

「安全質數產生器」(OSSL_PKEY_PARAM_DH_GENERATOR) <整數>

用於使用舊的安全質數產生器程式碼產生 DH 安全質數。預設值為 2。建議改用命名安全質數群組(如果需要網域參數驗證)。

FIPS 不允許隨機產生的安全質數,因此為 OpenSSL FIPS 提供者設定此值,將會根據 p 的大小選擇一個命名安全質數群組。

DH 和 DHX 領域參數 / 金鑰產生參數

除了所有 FFC 金鑰類型都應支援的常見 FFC 金鑰產生參數(請參閱 EVP_PKEY-FFC(7) 中的「FFC 金鑰產生參數」)之外,DHDHX 金鑰類型實作還支援下列項目

「類型」(OSSL_PKEY_PARAM_FFC_TYPE) <UTF8 字串>

設定參數產生類型。對於 DH,有效值為

「fips186_4」
「預設」
「fips186_2」

這些值在 EVP_PKEY-FFC(7) 中的「FFC 金鑰產生參數」 中有說明

「群組」

這表示將使用「pbits」類型選取已命名的安全質數名稱。

「產生器」

安全質數產生器。請參閱上方的「safeprime-generator」類型。這僅對 DH 金鑰有效。

「pbits」(OSSL_PKEY_PARAM_FFC_PBITS) <無符號整數>

設定質數 'p' 的大小(以位元為單位)。

對於「fips186_4」,此值必須為 2048。對於「fips186_2」,此值必須為 1024。對於「群組」,此值可以是 2048、3072、4096、6144 或 8192 之一。

「priv_len」(OSSL_PKEY_PARAM_DH_PRIV_LEN) <整數>

設定產生私鑰最大長度的選用值。如果未設定此值,則使用預設值,也就是 BN_num_bits(q)) 的最大值。可設定的最小值為 2 * s。其中 s 是金鑰的安全強度,其值為 112、128、152、176 和 200,分別對應金鑰大小 2048、3072、4096、6144 和 8192。

DH 金鑰驗證

對於非已命名群組的 DHX,FIPS186-4 標準規定,FFC 參數產生中使用的值也需要用於參數驗證。這表示可能需要儲存用於驗證目的的選用 FFC 領域參數值,例如 種子pcountergindexhindex。對於 DHX種子pcounter 可以儲存在 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) 符合 SP800-56Ar3 FFC 部分公鑰驗證,當 DH 金鑰為已核准的名稱安全質數群組時,否則與 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)

Copyright 2020-2021 The OpenSSL Project Authors。保留所有權利。

根據 Apache 授權條款 2.0(「授權條款」)授權。您不得使用此檔案,除非符合授權條款。您可以在原始程式碼散佈中的 LICENSE 檔案中取得副本,或至 https://www.openssl.org/source/license.html 取得。