C++/Windows下使用libcurl携带客户端证书调用API报CURLE_SSL_CERTPROBLEM问题
libcurl Schannel后端加载PEM客户端证书返回CURLE_SSL_CERTPROBLEM错误
我已在此处搜索,但未找到匹配的相关内容。我使用curl.exe测试是完全正常的,随后我尝试编写了一个小型测试程序:在VS2017中创建了一个Win32命令行项目,将simplessl.c中的代码复制进去。但问题在于,无论我尝试使用什么证书,始终会返回CURLE_SSL_CERTPROBLEM错误,该错误指向客户端证书异常。我甚至尝试了公开的2048位RSA证书和密钥,依旧报错,不清楚该如何排查问题。
测试程序代码
#include "pch.h" #include <iostream> #include <curl/curl.h> int main() { std::cout << "Hello World!\n"; CURL *curl; CURLcode res; FILE *headerfile; const char *pPassphrase = NULL; static const char *pCertFile = "C:\\Prog\\TestCurl\\2048b-rsa-example-cert.pem"; static const char *pCACertFile = "cacert.pem"; static const char *pHeaderFile = "C:\\Prog\\TestCurl\\requestWith.txt"; const char *pKeyName; const char *pKeyType; const char *pEngine; #ifdef USE_ENGINE pKeyName = "rsa_test"; pKeyType = "ENG"; pEngine = "chil"; /* for nChiper HSM... */ #else pKeyName = "C:\\Prog\\TestCurl\\2048b-rsa-example-keypair.pem"; pKeyType = "PEM"; pEngine = NULL; #endif headerfile = fopen(pHeaderFile, "wb"); curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if (curl) { /* what call to write: */ //curl_easy_setopt(curl, CURLOPT_URL, "https://pintatesti.vero.fi/FIS/Return/IIT/Test/GetWithholdingPercentage/v1"); curl_easy_setopt(curl, CURLOPT_URL, "https://www.pedago.fi"); curl_easy_setopt(curl, CURLOPT_HEADERDATA, headerfile); do { /* dummy loop, just to break out from */ if (pEngine) { /* use crypto engine */ if (curl_easy_setopt(curl, CURLOPT_SSLENGINE, pEngine) != CURLE_OK) { /* load the crypto engine */ fprintf(stderr, "can't set crypto engine\n"); break; } if (curl_easy_setopt(curl, CURLOPT_SSLENGINE_DEFAULT, 1L) != CURLE_OK) { /* set the crypto engine as default */ /* only needed for the first time you load a engine in a curl object... */ fprintf(stderr, "can't set crypto engine as default\n"); break; } } /* cert is stored PEM coded in file... */ /* since PEM is default, we needn't set it for PEM */ curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE, "PEM"); /* set the cert for client authentication */ curl_easy_setopt(curl, CURLOPT_SSLCERT, pCertFile); /* sorry, for engine we must set the passphrase (if the key has one...) */ if (pPassphrase) curl_easy_setopt(curl, CURLOPT_KEYPASSWD, pPassphrase); /* if we use a key stored in a crypto engine, we must set the key type to "ENG" */ curl_easy_setopt(curl, CURLOPT_SSLKEYTYPE, pKeyType); /* set the private key (file or ID in engine) */ curl_easy_setopt(curl, CURLOPT_SSLKEY, pKeyName); /* set the file with the certs vaildating the server */ //curl_easy_setopt(curl, CURLOPT_CAINFO, pCACertFile); /* disconnect if we can't validate server's cert */ curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); /* Perform the request, res will get the return code */ res = curl_easy_perform(curl); /* Check for errors */ if (res != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); /* we are done... */ } while (0); /* always cleanup */ curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; }
补充说明
- 我获取到的底层错误是*"schannel: certificate format compatibility error"*,我能找到的唯一相关记录是schannel.c中对P12类型的判断,但我的证书是PEM格式?
- 如果我将证书导入本地存储,程序确实可以运行,但我非常不希望采用这种方案。另外我发现调用
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);开启日志是非常好的排查手段,目前我已经有了进一步进展。 - 问题已经解决,和2019年Stack Overflow上的同类型客户端证书调用问题逻辑一致,不过我还是更希望直接使用证书文件的方案。
- 我使用的libcurl版本为*"libcurl/7.79.1 Schannel WinIDN"*
内容的提问来源于stack exchange,提问作者AndersG
相关产品推荐
相关产品推荐

