【问题标题】:C: client program reports SSL Certificate verify failed error with localCAC: 客户端程序报告 SSL Certificate verify failed 错误 with localCA
【发布时间】:2021-01-05 12:27:21
【问题描述】:

我正在编写一个简单的 TLS 客户端/服务器程序来安全地通过网络进行通信。最初,我在运行 RHEL 8.2 的同一台机器上构建和运行客户端和服务器。

首先,我正在为我的程序使用自定义自签名 ssl 证书和密钥。我已将 rootCA.crt(我的自定义 CA 证书放在 /root/CA/rootCA.crt 中)。还将rootCA.pem复制到/etc/pki/ca-trust/source/anchors/并执行update-ca-trust enable然后update-ca-trust extract将证书安装到系统。 (不确定是否需要重启系统才能生效。)

最初,客户端和服务器能够使用 TLS 进行通信,直到我在客户端添加了代码的证书验证部分。

证书验证sn-p:

ctx = SSL_CTX_new(method);   /* Create new context */
    if ( ctx == NULL )
    {
        ERR_print_errors_fp(stderr);
        abort();
    }

    SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);

    SSL_CTX_set_verify_depth(ctx, 4);

    const long flags = SSL_OP_NO_SSLv2 |
                        SSL_OP_NO_SSLv3 |
                        SSL_OP_NO_TLSv1 |
                        SSL_OP_NO_TLSv1_1 |
                        SSL_OP_NO_COMPRESSION;
    SSL_CTX_set_options(ctx, flags);

    if(SSL_CTX_load_verify_locations(ctx, NULL, 
                "/root/CA/") == 0){
        ERR_print_errors_fp(stderr);
        abort();
    }

ssl = SSL_new(ctx);      /* create new SSL connection state */
    SSL_set_fd(ssl, server);    /* attach the socket descriptor */
    if ( SSL_connect(ssl) == FAIL )   /* perform the connection */
        ERR_print_errors_fp(stderr);
    else
    {

        sprintf(acClientRequest, "%s", cpRequestMessage);   /* construct reply */
        printf("\n\nConnected with %s encryption\n", SSL_get_ciphe

}

当我运行服务器和客户端程序时,我看到以下错误 messafe =>

客户端: 140736372886336:错误:1416F086:SSL 例程:tls_process_server_certificate:证书验证失败:ssl/statem/statem_clnt.c:1915:

在服务器上: 140736022137664:error:14094418:SSL routines:ssl3_read_bytes:tlsv1 alert unknown ca:ssl/record/rec_layer_s3.c:1543:SSL alert number 48

不确定,证书验证过程出了什么问题。谁能建议我如何解决这个错误?

【问题讨论】:

    标签: c linux ssl openssl rhel


    【解决方案1】:

    仅将您的 rootCA.crt 文件复制到 /root/CA/ 是不够的。

    SSL_CTX_load_verify_locations 明确指出此目录中的文件必须使用特定格式:

    如果 CApath 不为 NULL,它指向一个包含 CA 的目录 PEM 格式的证书。每个文件都包含一个 CA 证书。 通过 CA 主题名称哈希值查找文件,该哈希值必须 因此可用。如果有多个同名 CA 证书 哈希值存在,扩展名必须不同(例如 9d66eef0.0, 9d66eef0.1 等)。搜索按顺序执行 分机号,无论证书的其他属性如何。 使用 c_rehash 实用程序创建必要的链接。

    因此,请确保您的 rootCa.crt 为 PEM 格式。然后生成所需的哈希并相应地重命名。以下命令生成哈希值。将文件重命名为<hashvalue>.0

    openssl x509 -inform PEM -subject_hash_old -in rootCa.crt | head -1
    

    如果您的代码仍然无法正常工作,我将首先测试您的代码是否可以正常工作。为此,请将服务器 URL 更改为使用已在您的系统上受信任的 HTTPS 证书的真实服务器。

    【讨论】:

    • 我尝试将同一目录 (/root/CA/) 中的 CA.crt 重命名为 .0。但是,问题仍然存在......我也尝试连接到 google.com 端口:443 并在那里看到同样的问题。好像我的客户端代码有问题。如果我注释掉客户端代码中的SSL_CTX_set_verifySSL_CTX_set_verify_depthSSL_CTX_load_verify_location 函数,我可以看到与服务器程序和google.com:443 的连接正常发生。您能告诉我如何正确验证收到的服务器证书吗?
    • 终于解决了这个问题。将 SSL_CTX_load_verify_location()function 调用更改为直接指向 rootCA 证书,而不是指向包含证书的目录。像:` if(SSL_CTX_load_verify_locations(ctx, "/root/CA/01c81d11.0", NULL)
    猜你喜欢
    • 2018-11-30
    • 2018-10-19
    • 1970-01-01
    • 2015-12-02
    • 1970-01-01
    • 2018-08-24
    • 2012-05-30
    • 2016-01-15
    • 1970-01-01
    相关资源
    最近更新 更多