【问题标题】:Authenticate server (peer) with SSL使用 SSL 验证服务器(对等体)
【发布时间】:2013-09-17 16:50:57
【问题描述】:

我希望我的 C/C++ 客户端通过 SSL 对服务器进行身份验证。 我首先使用
openssl s_client -showcerts -connect www.openssl.org:443 </dev/null 2>/dev/null | openssl x509 -outform PEM > mycertfile.pem

从服务器下载了证书文件

然后在我的应用程序中执行以下 API 调用(伪代码):


// Register the error strings for libcrypto & libssl
SSL_load_error_strings();
// Register the available ciphers and digests
SSL_library_init();
// New context saying we are a client, and using SSL 2 or 3
ctx = SSL_CTX_new(SSLv23_client_method());
// load the certificate
if(!SSL_CTX_load_verify_locations(ctx, "mycertfile.pem", 0))
  ...
// Create an SSL struct for the connection
ssl = SSL_new(ctx);
// Connect the SSL struct to our pre-existing TCP/IP socket connection
if (!SSL_set_fd(ssl, sd))
  ...
// Initiate SSL handshake
if(SSL_connect(ssl) != 1)
  ...
// form this point onwards the SSL connection is established and works
// perfectly, I would be able to send and receive encrypted data
// **Crucial point now**
// Get certificate (it works)
X509 *cert = SSL_get_peer_certificate(ssl);
if(cert) {
  // the below API returns code 19
  const long cert_res = SSL_get_verify_result(ssl);
  if(cert_res == X509_V_OK) {
    printf("Certificate verified!\n");
  }
  X509_free(cert);
}

如果我不介意检查证书并且我只对加密连接感兴趣,上面的代码可以正常工作。
问题在于,当我尝试验证服务器的真实性时,我确实SSL_get_peer_certificate 获得了证书,但是结果验证不起作用甚至如果我刚刚在 5 分钟前下载了证书。

我做错了什么?

所有这些都在带有 gcc 和 openssl 的 Ubuntu 12.04.03 x86-64 上。

谢谢, 埃玛

【问题讨论】:

    标签: c https openssl ssl-certificate


    【解决方案1】:

    如果您拥有比 OpenSSL 已经提供的更完整的 CA 证书集,或者如果您连接到使用非标准 CA 签署其证书的服务器,那么您应该只调用 SSL_CTX_load_verify_locations()你有 CA 证书来验证服务器证书。否则,您应该致电 SSL_CTX_set_default_verify_paths()

    // load the certificate^H^H^H^H^H^H^H^H^H^H^H^H CA trust-store
    if(!SSL_CTX_set_default_verify_paths(ctx))
      ...
    

    顺便说一句,您的程序有另一个错误。您将错误的指针传递给SSL_get_verify_result()。您应该传入SSL *,而不是传入SSL_CTX *。编译器应该警告你这个错误。

      const long cert_res = SSL_get_verify_result(ssl);
    

    【讨论】:

    • A pastebin 我用于测试的您的程序的简化版本。
    【解决方案2】:

    您刚刚下载的证书应该已由证书颁发机构 (CA) 签署。您需要加载 CA(或根 CA)的证书,而不是证书本身。由于您将服务器的证书直接加载到SSL_CTX_load_verify_locations,验证例程SSL_get_verify_result 返回一个失败代码。很可能验证码一定是 19 (X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN)。

    也就是说,OpenSSL 带有一组内置的 CA(和根 CA),您可以在客户端应用程序中使用它们。在 Linux 发行版上,这些证书的路径通常是 /etc/ssl/certs。因此,您可以尝试如下更改您的SSL_CTX_load_verify_locations

    if (!SSL_CTX_load_verify_locations(ctx, NULL, "/etc/ssl/certs"))
       ...
    

    当然,这假设 /etc/ssl/certs 存在并具有相关证书(其中一个签署了服务器证书)。如果您正在验证知名主机,您很可能会在 /etc/ssl/certs 中找到 CA。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-17
      • 2012-11-14
      • 2015-06-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多