OpenSSL向具有证书颁发机构的客户端提供服务器证书?

时间:2013-01-22 00:01:45

标签: c openssl mutual-authentication

我正在尝试学习如何使用OpenSSL库(总newb),并且在确定如何让客户端连接到具有正确证书的服务器时遇到一些麻烦,如果证书不正确则会失败。我的用例是构建一个没有中央CA的p2p应用程序,所以我不能依赖CA证书。具体来说,服务器像往常一样有证书/密钥,客户端将通过要求其他p2p节点投票来确定服务器的证书。

我有两个具体问题:

  • 在下面的代码片段中,我希望客户端如果我没有连接 注释掉“密码列表”下面的选择。它仍然有效!我错过了什么,对吗?
  • 有没有办法让客户端使用服务器证书,并且这足以打开连接?即没有钥匙,没有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。

1 个答案:

答案 0 :(得分:1)

SSL / TLS可以在不同模式下运行。最常见的模式是仅服务器身份验证,其中只有服务器具有证书和密钥。然后是相互认证模式,也称为客户端认证,其中客户端还具有(客户端)证书和密钥。然后有一个完全匿名的模式,服务器和客户端都不会自我验证,也不需要证书和密钥。

除非您告诉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!");

将导致客户端加载客户端证书(顺便说一下,您永远不必在客户端加载服务器证书和密钥)。但是,由于服务器不向客户端请求证书,因此客户端从不提供证书。对这些行进行注释会使客户端不加载任何客户端证书,因为它们没有被使用,所以没有任何区别。

要让服务器向客户端询问证书,并让服务器拒绝连接(如果没有提供),您必须告诉服务器这样(错误处理省略):

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函数发送了证书。