You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

嵌入式Linux设备OpenSSL连接自签名证书服务器验证失败求助

解决OpenSSL连接自签名服务器返回错误码18的问题

我来帮你搞定这个OpenSSL错误码18的问题——先明确一下,这个错误对应的是X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT,说白了就是OpenSSL在验证证书链的时候,发现最顶层的证书是自签名的,而你的代码默认没把它加入信任列表。

为啥浏览器和openssl s_client能成功?因为浏览器是你手动添加了信任,命令行大概率是用-CAfile参数指定了这个自签名证书,而你的代码里没做这一步,所以验证失败了。

下面给你几个排查和解决的方向:

  • 给代码的SSL上下文加载自签名证书
    这是最常见的原因:你的代码默认使用系统根证书池,而自签名证书不在这个池里。你需要手动把服务器的自签名证书加载到OpenSSL的信任存储中。
    示例代码(假设你已经创建好SSL_CTX* ctx):

    // 加载PEM格式的自签名证书文件
    if (!SSL_CTX_load_verify_locations(ctx, "/path/to/your/server.crt", NULL)) {
        ERR_print_errors_fp(stderr);
        // 处理加载失败的逻辑
        return -1;
    }
    

    如果你的证书是内嵌在代码中的(比如字节数组),可以用内存BIO加载:

    // cert_data是证书字节数组,cert_len是数组长度
    BIO *bio = BIO_new_mem_buf(cert_data, cert_len);
    X509 *cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
    if (cert) {
        // 将证书添加到SSL上下文的信任存储
        X509_STORE_add_cert(SSL_CTX_get_cert_store(ctx), cert);
        X509_free(cert);
    } else {
        ERR_print_errors_fp(stderr);
        // 错误处理
    }
    BIO_free(bio);
    
  • 检查证书路径与权限
    嵌入式设备上很容易犯这个错:代码里指定的证书路径不对,或者运行程序的用户没有读取证书文件的权限。而你用命令行测试时,可能用了绝对路径或者root权限,所以能成功。
    排查步骤:

    • 确保代码里用的是证书文件的绝对路径(嵌入式环境相对路径容易出问题)
    • 用ls -l /path/to/server.crt检查文件权限,确保运行程序的用户有读权限
  • 确认证书格式匹配
    OpenSSL加载证书时需要格式对应:如果你的证书是DER格式(没有-----BEGIN CERTIFICATE-----头),直接用SSL_CTX_load_verify_locations会失败。
    你可以用这个命令确认证书格式:

    openssl x509 -in server.crt -text -noout
    

    如果是DER格式,先转成PEM格式再用:

    openssl x509 -in server.der -inform der -out server.crt -outform pem
    
  • 检查SSL验证模式
    虽然可能性不大,但可以确认一下你的代码没有错误地修改验证模式。默认情况下OpenSSL是开启SSL_VERIFY_PEER的(要求验证服务器证书),如果被改成SSL_VERIFY_NONE就不会有错误,但你这里返回了错误码18,说明验证是开启的,这一步主要是排除误配置。

按照上面的步骤调整后,应该就能让代码成功验证自签名证书并建立SSL连接了。

内容的提问来源于stack exchange,提问作者MHD

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 07:15:33