【问题标题】:No peer certificate available with self signed certificate自签名证书没有可用的对等证书
【发布时间】:2017-05-31 12:14:20
【问题描述】:

我正在编写一个接受 SSL 连接的服务器。我已生成自签名证书:

openssl req -new -x509 -days 365 -nodes -out self.pem -keyout self.pem -subj "/CN=myhostname"

SSL_accept 失败并显示此消息:

140121764049248:error:1408A0C1:SSL routines:ssl3_get_client_hello:no shared cipher:s3_srvr.c:1417:

这是服务器代码的一部分:

  sslCtx = (SSL_CTX_new(SSLv23_server_method());
  if (!sslCtx){
      ERR_print_errors_fp(stderr);
    throw runtime_error("SSL_CTX_new failed");
  }
  ssl = SSL_new(sslCtx);
  if (!ssl)
    throw runtime_error("SSL_new failed");

  if (SSL_CTX_use_PrivateKey_file(sslCtx, keyFile.c_str(),
                                  SSL_FILETYPE_PEM) != 1)
    throw runtime_error("Unable to load private key file" + keyFile);

  if (SSL_CTX_use_certificate_file(sslCtx, certFile.c_str(),
                                   SSL_FILETYPE_PEM) != 1)
    throw runtime_error("Unable to load certificate file" + certFile);


  if (SSL_set_fd(ssl, socket) != 1)
    throw runtime_error("SSL_set_fd failed");

  if (SSL_accept(ssl) != 1){
     ERR_print_errors_fp(stderr);
    throw runtime_error("SSL_accept failed");
  }

我尝试测试服务器:

openssl s_client -cipher RSA -connect myhostname:33221 -tls1 -CApath . -servername myhostname

得到了

CONNECTED(00000003)
139898773520408:error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure:s3_pkt.c:1487:SSL alert number 40
139898773520408:error:1409E0E5:SSL routines:ssl3_write_bytes:ssl handshake failure:s3_pkt.c:656:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 7 bytes and written 0 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1
    Cipher    : 0000
    Session-ID: 
    Session-ID-ctx: 
    Master-Key: 
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    Start Time: 1496232544
    Timeout   : 7200 (sec)
    Verify return code: 0 (ok)
---

我使用的是 OpenSSL 1.0.2g。

【问题讨论】:

  • CN=myhostname 可能是错误的。主机名始终位于 SAN 中。如果它出现在 CN 中,那么它也必须出现在 SAN 中(在这种情况下您必须列出两次)。有关更多规则和原因,请参阅 How do you sign Certificate Signing Request with your Certification Authority 和 How to create a self-signed certificate with openssl? 您还需要将自签名证书放在适当的信任库中。
  • 请提供您用于连接服务器的 URL,并发布openssl s_client -connect <hostname>:<port> -tls1 -servername <hostname> | openssl x509 -text -noout 的输出。另请参阅 OpenSSL wiki 上的 TLS Client。它向您展示了如何在客户端的上下文中很好地配置SSL_CTX。其中大部分也适用于服务器。此外,这可能会给您带来麻烦:if (SSL_accept(ssl) != 1),尤其是在非阻塞套接字上。我似乎记得非阻塞套接字经常返回 -1 并且它不是错误。

标签: c++ ssl openssl ssl-certificate


【解决方案1】:

尝试SSL_new,仅在完全设置上下文并确保在程序开始时有OpenSSL_add_ssl_algorithms。 1.0.2 文档说它“继承”,但不确定这是否有效地意味着它会复制当时的设置并且不会应用进一步的更改。

https://www.openssl.org/docs/man1.0.2/ssl/SSL_new.html

新结构继承了底层上下文ctx的设置:连接方式(SSLv2/v3/TLSv1)、选项、验证设置、超时设置。

OpenSSL wiki上也有例子

没有错误处理的情况如下:

// General initialisation
SSL_load_error_strings();
OpenSSL_add_ssl_algorithms();
// Context for a server socket
ctx = SSL_CTX_new(SSLv23_server_method ()); //Note SSLv23_server_method in example is deprecated in favour of TLS_server_method for new versions. TLSv1_2_server_method will force TLS 1.2.
SSL_CTX_set_ecdh_auto(ctx, 1);
SSL_CTX_use_certificate_file(ctx, "cert.pem", SSL_FILETYPE_PEM);
SSL_CTX_use_PrivateKey_file(ctx, "key.pem", SSL_FILETYPE_PEM);
// Only after all certificates, and other config is set
ssl = SSL_new(ctx);
SSL_set_fd(ssl, client_socket);
SSL_accept(ssl);
// Use SSL_write and SSL_read
SSL_free(ssl);
close(client_socket);
// OpenSSL cleanup
EVP_cleanup();

【讨论】:

  • 仍然遇到同样的错误。也许我应该将证书复制到特定位置?
  • 你试试示例代码? SSL_CTX_use_certificate_file 等如果没有给出有效文件(它是一个正常的文件路径,所以 '/absolute' 或者相对于当前目录),应该会导致错误。因此,如果您在服务器代码中没有收到错误,那么您似乎做了与示例不同的事情。示例代码和同一系统上的openssl s_client 使用您显示的自签名命令行为我提供“验证返回代码:18(自签名证书)”。
  • 您是否跳过了您发布的代码之外的一些 OpenSSL 设置步骤? OpenSSL_add_ssl_algorithms 例如?
  • 我认为问题在于我正在使用带有 BIO-s 的非阻塞套接字,因此我必须以不同的方式处理握手。
  • 是的,如果你有一个非阻塞的socket,你需要处理SSL_ERROR_WANT_READ/WRITE,因为建立TLS连接需要多次往返。类似的适用于客户端。但在这种情况下,您应该看到 SSL_accept 失败并出现这样的错误,然后在您打印的消息中(请注意,SSL_accept 和 SSL_connect 都只是 SSL_do_handshake 周围的薄包装)。
猜你喜欢
  • 2014-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-23
  • 2019-12-11
  • 1970-01-01
  • 2018-05-11
  • 1970-01-01
相关资源
最近更新 更多