1

我正在尝试学习如何使用 OpenSSL 库(total newb)并且在弄清楚如何让客户端连接到具有正确证书的服务器时遇到了一些麻烦,如果证书不正确则失败。我的用例是构建一个没有中央 CA 的 p2p 应用程序,所以我不能依赖 CA 证书。具体来说,服务器和往常一样有一个cert/key,客户端会通过请求其他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。

4

1 回答 1

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在客户端未提供证书时导致服务器中止连接(请参阅文档)。如果您不使用后一个选项,您可以自行检查客户端是否使用SSL_get_peer_certificate函数发送了证书。

于 2013-01-22T00:24:58.410 回答