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

如何让OpenSSL在Linux/Windows10+系统中使用系统根CA证书

适配系统默认根CA证书的OpenSSL配置方案

现有代码与需求说明

用户提供的C代码用于初始化OpenSSL上下文,需求明确:

  • Windows XP环境:依赖程序附带的证书目录完成验证
  • Linux/Windows 10及以上环境:自动加载系统默认根CA证书,无需自带证书资源

原代码如下:

#include <stdio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>

#include <shlwapi.h>

#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)

#define _WINSOCK_DEPRECATED_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS


#include <winsock2.h>
#include <ws2tcpip.h>
#include <shlwapi.h>

// Need to link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib
#pragma comment (lib, "Ws2_32.lib")
//#pragma comment (lib, "Mswsock.lib")
//#pragma comment (lib, "AdvApi32.lib")


#define WIN32_LEAN_AND_MEAN


int verifyCerts( SSL_CTX* ctx )
{
    // directory where executable is
    char path[MAX_PATH] = "";
    
    memset(path, 0, MAX_PATH);
    GetModuleFileName(0, path, MAX_PATH);
    PathRemoveFileSpec(path);

    sprintf(path,"%s\\%s",path,"certificates");
    printf("\nCert path %s\n",path);
    sprintf(path,"%s\\%s",path,"certificates");
    printf("\nCert path %s\n",path);
    int value = SSL_CTX_load_verify_locations(ctx,NULL,path);
}

#else // By default use system's CA root

int verifyCerts( SSL_CTX* ctx )
{
       
}

#endif

SSL_CTX* InitCTX(void)
{
    OpenSSL_add_all_algorithms(); 
    SSL_load_error_strings();
    const SSL_METHOD* method = SSLv23_method();
    SSL_CTX* ctx = SSL_CTX_new(method);
    SSL_CTX_set_options(ctx, SSL_OP_ALL | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1);
    
    if (ctx == NULL)
    {
        ERR_print_errors_fp(stderr);
        abort();
    }
   
    int value = verifyCerts( ctx );
    if(value == 0) {
        printf("Certificate error\n");
        exit(1);
    }

    SSL_CTX_set_verify(ctx,SSL_VERIFY_PEER,NULL);

    return ctx;
}

针对不同系统的配置实现

1. 修正原代码的基础问题

原Windows XP分支中重复拼接两次"certificates",导致路径错误,需先修正为仅拼接一次。

2. Linux系统配置

Linux系统中,OpenSSL默认会识别系统根CA的标准路径(如/etc/ssl/certs/或/etc/ssl/certs/ca-certificates.crt),只需调用SSL_CTX_set_default_verify_paths即可自动加载:

#else // Linux系统
int verifyCerts(SSL_CTX* ctx)
{
    // 加载系统默认CA证书路径
    if (SSL_CTX_set_default_verify_paths(ctx) != 1) {
        ERR_print_errors_fp(stderr);
        return 0;
    }
    return 1;
}
#endif

3. Windows 10及以上系统配置

通过_WIN32_WINNT宏区分Windows版本(XP对应0x0501,Win10对应0x0A00),在高版本系统中调用SSL_CTX_set_default_verify_paths加载系统根证书存储:

#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)

#define _WINSOCK_DEPRECATED_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS

#include <winsock2.h>
#include <ws2tcpip.h>
#include <shlwapi.h>

// Need to link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib
#pragma comment (lib, "Ws2_32.lib")
//#pragma comment (lib, "Mswsock.lib")
//#pragma comment (lib, "AdvApi32.lib")

#define WIN32_LEAN_AND_MEAN

int verifyCerts(SSL_CTX* ctx)
{
    // 判断是否为Windows XP
#if (_WIN32_WINNT <= _WIN32_WINNT_WINXP)
    // XP逻辑:使用程序附带的certificates目录
    char path[MAX_PATH] = "";
    
    memset(path, 0, MAX_PATH);
    GetModuleFileName(0, path, MAX_PATH);
    PathRemoveFileSpec(path);

    sprintf(path,"%s\\%s", path, "certificates");
    printf("\nCert path %s\n", path);
    
    int value = SSL_CTX_load_verify_locations(ctx, NULL, path);
    return value;
#else
    // Windows 10及以上:加载系统默认根CA
    if (SSL_CTX_set_default_verify_paths(ctx) != 1) {
        ERR_print_errors_fp(stderr);
        return 0;
    }
    return 1;
#endif
}

#endif

4. 编译与版本注意事项

  • 编译Windows程序时,需手动指定_WIN32_WINNT宏:编译XP版本定义_WIN32_WINNT=0x0501,Win10+版本定义_WIN32_WINNT=0x0A00,确保版本判断生效。
  • 确保使用OpenSSL 1.1.0及以上版本,该版本对Windows系统根证书的加载支持更完善;若使用旧版OpenSSL,需通过Windows CryptoAPI(如CertOpenSystemStore)手动导入系统根证书,但推荐升级版本简化实现。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 15:48:30