You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

编译带-DENABLE_SSL=WINDOWS的mongocxx驱动时带密码PEM密钥连接失败

解决mongocxx驱动(Windows Schannel后端)带密码PEM私钥连接失败问题

问题背景

你遇到的情况是:当编译mongocxx驱动时指定-DENABLE_SSL=WINDOWS(使用Windows Secure Channel/Schannel作为SSL后端),客户端使用带密码的PEM私钥连接MongoDB时失败,报错:

[error@stream-secure-channel] Failed to parse private key. ASN1 bad tag value met. (0x8009310B)
[warning@stream-secure-channel] a client certificate has been requested

而用mongo.exe却能正常连接,且切换到-DENABLE_SSL=OPENSSL编译驱动后问题消失。

原因分析

Windows Schannel对PEM格式私钥的处理逻辑和OpenSSL有差异:

  • 你用openssl genrsa -des3 -out server.key 2048生成的是PKCS#1格式的加密私钥,Schannel对这种格式的加密私钥兼容性较差;
  • mongo.exe可能在Windows环境下默认仍使用OpenSSL处理SSL,或者内部做了格式兼容转换,所以能正常解析;
  • 当驱动用Schannel后端时,它严格遵循Schannel的要求,无法直接解析PKCS#1格式的加密私钥,导致ASN1解析错误。

解决方案

1. 将PKCS#1私钥转换为PKCS#8格式

Schannel对PKCS#8格式的加密私钥支持更好,用OpenSSL命令转换:

# 转换私钥为PKCS#8格式,会提示输入原密码和设置新密码(可设为原密码1234)
openssl pkcs8 -topk8 -in server.key -out server_pkcs8.key -v2 des3

然后将转换后的server_pkcs8.key和你的证书合并成新的PEM文件(如果之前是证书+私钥合并的cry.pem):

cat your_cert.pem server_pkcs8.key > new_cry.pem

之后在mongocxx中使用这个新的new_cry.pem文件尝试连接。

2. 确保代码中正确传递私钥密码

检查你的mongocxx客户端代码,是否明确设置了PEM私钥的密码。示例代码如下:

#include <mongocxx/client.hpp>
#include <mongocxx/instance.hpp>
#include <mongocxx/uri.hpp>
#include <mongocxx/options/client.hpp>
#include <mongocxx/options/ssl.hpp>

int main() {
    mongocxx::instance instance{};

    // 构建连接URI
    mongocxx::uri uri("mongodb://user1:123@10.154.10.39/?authSource=admin&ssl=true");

    // 配置SSL选项
    mongocxx::options::ssl ssl_opts;
    ssl_opts.ca_file("d:/ca.pem");
    ssl_opts.pem_file("d:/cry.pem"); // 或转换后的new_cry.pem
    ssl_opts.pem_password("1234");   // 必须明确设置私钥密码

    // 配置客户端选项
    mongocxx::options::client client_opts;
    client_opts.ssl_opts(ssl_opts);

    // 尝试连接
    try {
        auto client = mongocxx::client(uri, client_opts);
        // 连接成功,执行后续操作
        std::cout << "Connected successfully!" << std::endl;
    } catch (const std::exception& e) {
        std::cerr << "Connection failed: " << e.what() << std::endl;
    }

    return 0;
}

如果之前的代码遗漏了pem_password的设置,Schannel无法解密私钥,也会导致解析失败。

3. 辅助检查:确认系统证书信任(可选)

如果转换格式和设置密码后仍有问题,可以尝试将CA证书导入到Windows的受信任根证书颁发机构存储中:

  • 右键点击ca.pem,选择「安装证书」
  • 选择「本地计算机」,然后按向导将证书放入「受信任的根证书颁发机构」目录

这一步主要解决证书信任问题,但你的错误是私钥解析,所以优先级低于前两个方案。

验证

完成上述步骤后,重新编译运行mongocxx客户端,应该能正常连接MongoDB了。

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

火山引擎 最新活动