首页 > 解决方案 > 如果我无法提供私钥,如何进行“客户端身份验证”

问题描述

我想设置我的本地服务器以与我的客户进行通信。他们使用 Openssl 建立 TLS 连接。我尝试实现双面身份验证,例如服务器将验证客户端,客户端也需要验证服务器。

当我使用自己生成的证书时,一切正常。代码如下。它是客户端中的 C++ 代码。我设置了客户端证书、私钥和中间证书。在服务器端,我保存了一个 CA 证书。

关系是:CA签署中间证书,中间证书签署客户端证书。

众所周知,我们需要提供客户端私钥的原因是客户端将签署一个“挑战”然后发送到服务器。服务器可以通过证书链获取客户端公钥,并使用它来解码加密“挑战”以查看它们是否匹配。您可以查看此链接了解详细过程: https ://en.wikipedia.org/wiki/Transport_Layer_Security#TLS_handshake

但是在我的场景中,我无权获取私钥。我只有一个 API 可以调用,它将摘要或我们想要编码的任何内容作为输入,并返回由客户端私钥编码的字符串。

因此,我无法将任何“ClientPrivateKeyFileTest”传递给 TLS。

我搜索了 openssl 源代码,但所有握手都在这个函数中完成:SSL_do_handshake(),我不允许修改这个函数。

// load client-side cert and key
SSL_CTX_use_certificate_file(m_ctx, ClientCertificateFileTest, SSL_FILETYPE_PEM);
SSL_CTX_use_PrivateKey_file(m_ctx, ClientPrivateKeyFileTest, SSL_FILETYPE_PEM);

// load intermediate cert
X509* chaincert = X509_new();
BIO* bio_cert = BIO_new_file(SignerCertificateFileTest, "rb");
PEM_read_bio_X509(bio_cert, &chaincert, NULL, NULL);
SSL_CTX_add1_chain_cert(m_ctx, chaincert)

m_ssl = SSL_new(m_ctx);

// get_seocket is my own API
m_sock = get_socket();

SSL_set_fd(m_ssl, m_sock)

// doing handshake and build connection
auto r = SSL_connect(m_ssl);

我认为所有握手过程都会在我调用 SSL_connect() 之后完成。所以我想知道还有其他方法可以完成客户端身份验证吗?

例如,我可以跳过添加私钥的步骤,但在某处设置一个回调函数,当 SSL 需要使用私钥进行计算时,它可以处理所有情况。

PS:API 是客户端机器中的一个黑盒子。

还有一件事,这些天我发现 openssl 引擎可能有助于解决这个问题。但是有人知道什么样的引擎对这个问题有用吗?EC标志,验证还是其他?

最后更新:我实现了一个 OpenSSL 引擎来重新加载 EC_KEY_METHOD 以便我能够使用我自己的签名功能。

非常感谢!

标签: c++opensslprivate-keyclient-certificates

解决方案


推荐阅读