从缓冲区到EVP_PKEY的OpenSSL服务器公钥

从缓冲区到EVP_PKEY的OpenSSL服务器公钥,openssl,tls1.2,public-key,ecdh,Openssl,Tls1.2,Public Key,Ecdh,我正在编程一个客户端,它通过连接到谷歌服务器的TCP套接字发送消息,参与TLS1.2握手。我正在使用ECDH密钥交换方法 我正在尝试使用代码导出共享秘密 我通过serverKeyExchange消息接收密钥并将其存储在缓冲区中,因此我的问题是:如何从缓冲区生成EVP_PKEY? 我在post中找到了一个可能的解决方案,并尝试了: i2d_PublicKey(peerkey, (unsigned char **) &server_pub_key) 但是当我运行代码时,我在这一步中得到一个

我正在编程一个客户端,它通过连接到谷歌服务器的TCP套接字发送消息,参与TLS1.2握手。我正在使用ECDH密钥交换方法

我正在尝试使用代码导出共享秘密

我通过serverKeyExchange消息接收密钥并将其存储在缓冲区中,因此我的问题是:如何从缓冲区生成EVP_PKEY? 我在post中找到了一个可能的解决方案,并尝试了:

i2d_PublicKey(peerkey, (unsigned char **) &server_pub_key)
但是当我运行代码时,我在这一步中得到一个错误:

/* Provide the peer public key */
    if(1 != EVP_PKEY_derive_set_peer(ctx, peerkey)) handleErrors();
这让我觉得我没有成功地检索到服务器公钥


有什么建议吗?我怎么知道密钥是否已成功编码?

如果您拥有原始公钥,则必须使用正确的参数创建EC_密钥

EVP_PKEY * get_peerkey(const unsigned char * buffer, size_t buffer_len)
{
    EC_KEY *tempEcKey = NULL;
    EVP_PKEY *peerkey = NULL;

    // change this if another curve is required
    tempEcKey = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
    if(tempEcKey == NULL) {
        handleErrors();
    }

    if(EC_KEY_oct2key(tempEcKey, buffer, buffer_len, NULL) != 1)  {
        handleErrors();
    }

    if(EC_KEY_check_key(tempEcKey) != 1) {
        handleErrors();
    }

    peerkey = EVP_PKEY_new();
    if(peerkey == NULL) {
        handleErrors();
    }

    if(EVP_PKEY_assign_EC_KEY(peerkey, tempEcKey)!= 1) {
        handleErrors();
    }

    return peerkey;
}
如果将公钥作为ASN.1序列,则可以使用内部转换方法:

EVP_PKEY* get_peerkey(const unsigned char *buffer, size_t buffer_len)
{
    EVP_PKEY *peerkey = NULL;       
    const unsigned char *helper = buffer;

    // from "openssl/x509.h"
    peerkey = d2i_PUBKEY(NULL, &helper, buffer_len);
    if (!peerkey) {
        handleErrors();
        return NULL;
    }

    return peerkey;
}

i2d_公钥用于另一个方向,它从peerkey获取EVP_PKEY,将其转换为der并存储在服务器_pub_密钥中。谢谢。那么d2i_Publickey是否应该完成任务?这取决于der缓冲区中存储的内容。您可以发布用于转换缓冲区的完整代码吗?很抱歉这个愚蠢的问题,但是“您用于转换缓冲区的代码”是指我正在尝试执行的转换代码还是将密钥存储到缓冲区的代码?如果您确定缓冲区包含正确格式的数据,然后只有那个试图用它来创建EVP_PKEY的部分。我无法让它工作。你能看一下我的密码吗?(无论如何,感谢您在这方面花费时间)首先,我必须道歉,我认为您将公钥作为Asn.1序列而不是原始缓冲区获取,在您的情况下,我的解决方案将不起作用,并且应该报告错误。我更新了我的答案来处理这两种情况(公钥作为Asn.1序列,公钥作为原始缓冲区)。我在你的代码中发现了一些错误,使其无法正常运行,我将在github上向你发送一份PR,其中包含已修复的错误和已更正的转换。这很有效!非常感谢你,我真的被困住了。误解可能是因为我解释得不好。