【问题标题】:OpenSSL server public key from buffer to EVP_PKEY从缓冲区到 EVP_PKEY 的 OpenSSL 服务器公钥
【发布时间】:2019-10-23 09:58:27
【问题描述】:

我正在编写一个客户端,该客户端通过连接到 Google 服务器的 TCP 套接字发送消息来参与 TLS 1.2 握手。我正在使用 ECDH 密钥交换方法。

我正在尝试使用this 代码导出共享密钥。

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

i2d_PublicKey(peerkey, (unsigned char **) &server_pub_key)

但是当我运行代码时,我在这一步中遇到了错误:

/* Provide the peer public key */
    if(1 != EVP_PKEY_derive_set_peer(ctx, peerkey)) handleErrors();

这让我觉得我没有成功检索服务器公钥。

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

【问题讨论】:

  • i2d_PublicKey 用于另一个方向,它从 peerkey 中获取 EVP_PKEY,将其转换为 der 并将其存储在 server_pub_key 中。
  • 谢谢。那么 d2i_Publickey 是否应该完成这项工作?
  • 这取决于存储在 der 缓冲区中的内容。您可以发布用于转换缓冲区的完整代码吗?
  • 抱歉这个愚蠢的问题,但是“您用来转换缓冲区的代码”是指我正在尝试执行的转换代码还是将密钥存储到缓冲区?
  • 如果您确定缓冲区包含正确格式的数据,那么只有尝试从中创建 EVP_PKEY 的部分。

标签: openssl tls1.2 public-key ecdh


【解决方案1】:

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

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;
}

【讨论】:

  • 我无法让它工作。你能看看我的代码吗? (无论如何,谢谢你花时间在这上面)github.com/BalzPit/TLS-1.2-client-handshake
  • 首先我要道歉,我认为您将公钥作为 Asn.1 序列而不是作为原始缓冲区获取,在您的情况下,我的解决方案将不起作用并且应该报告错误。我更新了我的答案以处理这两种情况(公钥作为 Asn.1 序列,公钥作为原始缓冲区)。我在您的代码中发现了一些导致其无法正常运行的错误,我将在 github 上向您发送一个 PR,其中包含已修复的错误和更正的转换。
  • 这行得通!非常感谢,我真的被困住了。误会可能是我解释不当造成的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-10-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-11
  • 1970-01-01
  • 2014-09-11
相关资源
最近更新 更多