如何在OpenSSL 3.0中使用EVP接口实现ECDH密钥交换?
OpenSSL 3.0下EVP接口实现ECDH公钥导出与密钥派生
在OpenSSL 3.0中,EC_KEY_get0_public_key这类EC_KEY*系列API已被弃用,只能使用EVP接口。我的需求是将公钥导出到缓冲区,对其计算MAC,接收端验证MAC后再用该密钥进行DH密钥交换。
我已经成功生成了包含EC密钥的EVP_PKEY对象,但无法提取公钥(原始字节)和群组名称,没法重建ECDH密钥交换。
void generateAndExport() { /* params have been set */ EVP_PKEY_CTX *keygen_ctx; EVP_PKEY *ec_key; size_t pubkey_size; if (!(keygen_ctx = EVP_PKEY_CTX_new(ec_params, NULL))) return -1; if (!EVP_PKEY_keygen_init(keygen_ctx)) return -1; if (!EVP_PKEY_keygen(keygen_ctx, &ec_key)) return -1; pubkey_size = 0; /* Query the buffer size */ if (!EVP_PKEY_get_octet_string_param( ec_key, OSSL_PKEY_PARAM_PUB_KEY, NULL, 0, &pubkey_size)) return -1; /* Allocate the buffer for the public key */ if (!(ec_pub = calloc(1, pubkey_size))) return -1; /* Get the public key */ if (!EVP_PKEY_get_octet_string_param(ec_key, OSSL_PKEY_PARAM_PUB_KEY, ec_pub, pubkey_size, &pubkey_size)) return -1; /* calculate a MAC over the public key */ cleanup: EVP_PKEY_CTX_free(keygen_ctx); EVP_PKEY_free(ec_key); return 0; }
编辑: 以下是实现需求的正确代码。如果有人需要,我附上用于恢复公钥并派生共享密钥的代码:
void deriveSharedSecret(EVP_PKEY *priv, unsigned char *pkey, size_t pkey_len, unsigned char *group_name, unsigned char **shared_key, size_t *shared_key_len) { EVP_PKEY_CTX *derive_ctx = NULL; EVP_PKEY *peer_key = NULL; CHECK(pkey && (pkey_len > 0)); CHECK(!(peer_key = EVP_PKEY_new_raw_public_key( EVP_PKEY_EC, NULL, pkey, pkey_len))); CHECK(derive_ctx = EVP_PKEY_CTX_new(priv, NULL)); CHECK(EVP_PKEY_derive_init(derive_ctx)); CHECK(EVP_PKEY_CTX_set_group_name(derive_ctx, group_name)); CHECK(EVP_PKEY_derive_set_peer(derive_ctx, peer_key)); /* Query buffer size for shared secret */ *shared_key_len = 0; CHECK(EVP_PKEY_derive(derive_ctx, NULL, shared_key_len)); if (!(*shared_key = calloc(1, *shared_key_len))) return -1; CHECK(EVP_PKEY_derive(derive_ctx, *shared_key, shared_key_len)); EVP_PKEY_free(peer_key); EVP_PKEY_CTX_free(derive_ctx); return 0; }
另外,获取群组名称的代码如下:
unsigned char groupname[MAX_GROUP_NAME_SIZE]; size_t groupname_len; CHECK(EVP_PKEY_get_octet_string_param( ec_key, OSSL_PKEY_PARAM_GROUP_NAME, groupname, 0, &groupname_len));
内容的提问来源于stack exchange,提问作者vibhav950
相关产品推荐
相关产品推荐

