我正在尝试学习如何使用 OpenSSL 库(total newb)并且在弄清楚如何让客户端连接到具有正确证书的服务器时遇到了一些麻烦,如果证书不正确则失败。我的用例是构建一个没有中央 CA 的 p2p 应用程序,所以我不能依赖 CA 证书。具体来说,服务器像往常一样有一个证书/ key ,客户端将通过要求其他 p2p 节点投票来确定服务器的证书。
我有两个具体问题:
- 在下面的代码片段中,如果我希望客户端不会连接 注释掉“密码列表”下方的选择。它仍然有效!我错过了什么,对吗?
- 有没有办法让客户端使用服务器证书,并且足以打开连接?即没有 key ,没有 CA?
客户:
ctx = SSL_CTX_new(DTLSv1_client_method());
SSL_CTX_set_cipher_list(ctx, "HIGH:!DSS:!aNULL@STRENGTH");
// If I comment out below stuff, client still connects happily!?
if (!SSL_CTX_use_certificate_file(ctx, "certs/server-cert.pem", SSL_FILETYPE_PEM))
printf("\nERROR: no certificate found!");
if (!SSL_CTX_use_PrivateKey_file(ctx, "certs/server-key.pem", SSL_FILETYPE_PEM))
printf("\nERROR: no private key found!");
if (!SSL_CTX_check_private_key (ctx))
printf("\nERROR: invalid private key!");
服务器:
SSL_CTX_set_cipher_list(ctx, "HIGH:!DSS:!aNULL@STRENGTH"); // high strength ciphers
SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
if (!SSL_CTX_use_certificate_file(ctx, "certs/server-cert.pem", SSL_FILETYPE_PEM))
printf("\nERROR: no certificate found!");
if (!SSL_CTX_use_PrivateKey_file(ctx, "certs/server-key.pem", SSL_FILETYPE_PEM))
printf("\nERROR: no private key found!");
if (!SSL_CTX_check_private_key (ctx))
printf("\nERROR: invalid private key!");
我的代码在 https://github.com/a34729t/exp/tree/master/tun2udp/dtls ;它由 Robin Seggelmann 的 DTLS 示例构建而成。具体来说,我正在使用 server3_oo.c。
最佳答案
SSL/TLS 可以在不同的模式下运行。最常见的模式是server authentication only,即只有服务器有证书和 key 。然后是相互认证模式,也称为客户端认证,其中客户端也有一个(客户端)证书和 key 。然后是完全匿名模式,其中服务器和客户端都不验证自己,也不需要证书和 key 。
除非您以其他方式告诉 OpenSSL,否则它将在仅服务器身份验证模式下运行。在这种模式下,客户端中的这些行:
if (!SSL_CTX_use_certificate_file(ctx, "certs/server-cert.pem", SSL_FILETYPE_PEM))
printf("\nERROR: no certificate found!");
if (!SSL_CTX_use_PrivateKey_file(ctx, "certs/server-key.pem", SSL_FILETYPE_PEM))
printf("\nERROR: no private key found!");
将导致客户端加载客户端证书(顺便说一句,您永远不必在客户端加载服务器 证书和 key )。但是,由于服务器不要求客户端提供证书,因此客户端永远不会出示证书。注释掉这些行会使客户端不加载任何客户端证书,这没有任何区别,因为它们无论如何都不会被使用。
要让服务器向客户端请求证书,并在没有提供证书的情况下让服务器拒绝连接,您必须这样告诉服务器(省略错误处理):
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
SSL_VERIFY_PEER
使服务器请求客户端证书,而 SSL_VERIFY_FAIL_IF_NO_PEER_CERT
使服务器在客户端未提供证书时中止连接(参见 documentation )。如果您不使用后一个选项,您可以自己检查客户端是否使用 SSL_get_peer_certificate 发送了证书。功能。
关于c - OpenSSL 向具有证书颁发机构的客户端提供服务器证书?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14449381/