如何在C++的libcurl中使用curl_blob加载嵌入式证书实现mTLS请求
curl_blob 结构体使用说明
curl_blob 是 libcurl 提供的专用于传递内存中二进制数据的结构体,恰好适配不用外部证书文件、直接用内置嵌入式证书的需求。各字段的使用规则如下:
各属性说明
data:指向内存中证书数据的首地址- C++ 场景下,如果你将证书内容存在
std::string、std::vector<uint8_t>或者编译期嵌入的静态数组中,直接传入对应数据的指针即可,比如std::string就传str.c_str(),vector就传vec.data()。 - 如果是 P12 这类二进制格式证书,不要使用 C 字符串相关的截断操作,避免证书内容因包含
\0字符被破坏。
- C++ 场景下,如果你将证书内容存在
len:证书数据的实际字节长度- 直接取存储容器的大小即可:
std::string用str.size(),vector用vec.size(),编译期嵌入的数组用sizeof(数组名)。 - 禁止用
strlen()计算长度,二进制证书中间的\0会导致strlen返回的长度小于实际证书长度,最终TLS握手失败。
- 直接取存储容器的大小即可:
flags:控制 libcurl 对传入内存的处理逻辑,常用两个取值:CURL_BLOB_COPY:libcurl 会内部复制一份你传入的证书数据,之后你可以随时释放原数据内存,不会影响 curl 的请求执行,适合证书存放在临时变量的场景,绝大多数场景优先用这个选项,不容易出现内存问题。CURL_BLOB_NOCOPY:libcurl 直接复用你传入的指针,不会做内存拷贝,你需要保证在curl_easy_perform执行完成、curl 实例被清理前,这块证书内存一直有效,适合全局静态存储的证书,可以省一次内存拷贝开销。
完整C++使用示例
你可以先用xxd工具将本地证书文件转换成C语言数组头文件,直接嵌入到源码中:
# 执行该命令会生成cert.h,里面包含cert_p12数组和cert_p12_len两个全局变量 xxd -i your_cert.p12 cert.h
业务代码示例:
#include <curl/curl.h> #include <iostream> // 嵌入生成的证书头文件 #include "cert.h" int main() { CURL* curl = curl_easy_init(); if (curl) { struct curl_blob cert_blob; cert_blob.data = cert_p12; cert_blob.len = cert_p12_len; // 优先用COPY选项,避免内存问题 cert_blob.flags = CURL_BLOB_COPY; // curl基础配置 curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/"); // 传入客户端证书blob curl_easy_setopt(curl, CURLOPT_SSLCERT_BLOB, &cert_blob); // 证书类型,PEM格式填"PEM"即可 curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE, "P12"); // 证书密码,无密码可以不传该配置 curl_easy_setopt(curl, CURLOPT_KEYPASSWD, "your_cert_password"); // 如果需要配置CA根证书、客户端私钥,也有对应的BLOB选项: // curl_easy_setopt(curl, CURLOPT_CAINFO_BLOB, &ca_blob); // curl_easy_setopt(curl, CURLOPT_SSLKEY_BLOB, &key_blob); CURLcode res = curl_easy_perform(curl); if (res != CURLE_OK) { std::cout << "请求失败: " << curl_easy_strerror(res) << std::endl; } curl_easy_cleanup(curl); } return 0; }
注意事项
libcurl版本要求:CURLOPT_SSLCERT_BLOB这类BLOB相关配置是7.71.0版本才新增的,低于该版本的libcurl会编译报错,需要先升级库版本。
内容的提问来源于stack exchange,提问作者Renis1235
相关产品推荐
相关产品推荐

