如何让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
相关产品推荐
相关产品推荐

