Leo*_*Leo 6 c c++ openssl diffie-hellman
在 OpenSSL3 之前,这很简单。
DH* dh = DH_new();
/* Parameters */
dh->p = BN_bin2bn(bin_p, bin_p_size, NULL);
dh->g = BN_bin2bn(bin_g, bin_g_size, NULL);
/* Private key generation */
BN_hex2bn(&dh->priv_key, hex_priv_key);
/* Public key generation */
DH_generate_key(dh);
/* Derive */
int shared_key_size = DH_compute_key(shared_key, peer_pub_key, dh);
Run Code Online (Sandbox Code Playgroud)
我正在尝试在新版本的 OpenSSL 中创建密钥,但它不起作用,因为 EVP_PKEY_generate 失败并出现错误:03000097:数字信封例程::操作未初始化
OSSL_PARAM_BLD* param_build = OSSL_PARAM_BLD_new();
OSSL_PARAM_BLD_push_BN(param_build, OSSL_PKEY_PARAM_FFC_P, p);
OSSL_PARAM_BLD_push_BN(param_build, OSSL_PKEY_PARAM_FFC_G, g);
OSSL_PARAM* params = OSSL_PARAM_BLD_to_param(param_build};
/* DH_new() */
EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new_from_name(nullptr, "DH", nullptr);
EVP_PKEY_keygen_init(ctx);
/* DH_generate_key */
EVP_PKEY* dh_key_pair = NULL;
EVP_PKEY_generate(ctx, &dh_key_pair, EVP_PKEY_KEY_PARAMETERS, params);
Run Code Online (Sandbox Code Playgroud)
互联网上缺乏信息。我不知道该怎么办。
如果您使用自定义素数和生成器,则必须首先创建带有域参数的 EVP_PKEY 。
// Create the OSSL_PARAM_BLD.
OSSL_PARAM_BLD* paramBuild = OSSL_PARAM_BLD_new();
if (!paramBuild) {
// report the error
}
// Set the prime and generator.
if (!OSSL_PARAM_BLD_push_BN(paramBuild, OSSL_PKEY_PARAM_FFC_P, prime) ||
!OSSL_PARAM_BLD_push_BN(paramBuild, OSSL_PKEY_PARAM_FFC_G, generator)) {
// report the error
}
// Convert to OSSL_PARAM.
OSSL_PARAM* param = OSSL_PARAM_BLD_to_param(paramBuild);
if (!param) {
// report the error
}
// Create the context. The name is DHX not DH!!!
EVP_PKEY_CTX* domainParamKeyCtx = EVP_PKEY_CTX_new_from_name(nullptr, "DHX", nullptr);
if (!domainParamKeyCtx) {
// report the error
}
// Initialize the context.
if (EVP_PKEY_fromdata_init(domainParamKeyCtx) <= 0) {
// report the error
}
// Create the domain parameter key.
EVP_PKEY* domainParamKey = nullptr;
if (EVP_PKEY_fromdata(domainParamKeyCtx, &domainParamKey,
EVP_PKEY_KEY_PARAMETERS, param) <= 0) {
// report the error
}
Run Code Online (Sandbox Code Playgroud)
域参数domainParamKey已准备就绪!现在,用它来创建密钥对。
EVP_PKEY_CTX* keyGenerationCtx = EVP_PKEY_CTX_new_from_pkey(nullptr, domainParamKey, nullptr);
if (!keyGenCtx) {
// report the error
}
if (EVP_PKEY_keygen_init(keyGenerationCtx) <= 0) {
// report the error
}
EVP_PKEY* keyPair = nullptr;
if (EVP_PKEY_generate(keyGenerationCtx, &keyPair) <= 0) {
// report the error
}
Run Code Online (Sandbox Code Playgroud)
密钥对keyPair已准备就绪!
请在 GitHub 上查看此项目:https ://github.com/eugen15/diffie-hellman-cpp 。它展示了如何生成密钥对、设置和获取 Diffie-Hellman 参数。另外,它还有一些自定义的 Diffie-Hellman 实现。
请参阅以下文件了解 OpenSSL 3 示例:
以下文件是 LibreSSL 示例,基本上是版本 3 之前的 OpenSSL。这是为了确保您具有向后兼容性。
更多需要考虑的事情
第一的
如果您在 OpenSSL 3 之前使用了自定义素数,那么最好改用预定义的安全素数。您可以在此处查看示例:https ://www.openssl.org/docs/manmaster/man7/EVP_PKEY-DH.html
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);
Run Code Online (Sandbox Code Playgroud)
Alice执行上述代码(摘自 OpenSSL 手册)。然后你得到素数和生成元:
EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_FFC_P, &prime);
EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_FFC_G, &generator);
Run Code Online (Sandbox Code Playgroud)
然后将其发送给Bob并使用我上面的代码来创建密钥对。
第二
对新项目使用椭圆曲线 Diffie-Hellman (ECDH) 密钥交换。它要快得多。留下你的 DH 作为后备。请参阅此处的示例。