双向认证:
1.服务器回验证客户端上报的证书
2.客户端回验证服务器的证书
而证书一般分为:1.受信任的根证书,2不受信任的根证书。
但是由于各种限制不想在libcurl中增加openssl,那么使用默认的winssl也可以完成以上两种证书的双向认证,以下是亲测代码:
static int http_write(char* data, size_t size, size_t nmemb, std::string* writerData)
{
unsigned long sizes = size * nmemb;
if (writerData == NULL)
return-1;
writerData->append(data, sizes);
return sizes;
}
int main_curl(void)
{
CURL* curl;
CURLcode res = CURLE_OK;
const char* pPassphrase = NULL; //password for private key
static const char* pCACertFile = "C:\\ca.crt"; //CA root certificat
static const char* pCertFile = "C:\\client.p12"; //client certificate
static const char* pKeyName = "C:\\client.key"; // private.key
static const char* pHeaderFile = "dumpit";
const char* pKeyType;
const char* pEngine;
pKeyType = "PEM";
pEngine = NULL;
std::string sRes;
char* url = "https://xxx.com";
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
/* what call to write: */
curl_easy_setopt(curl, CURLOPT_URL, url);
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;
}
}
//winssl 必须是P12证书类型,不能设置其参数,openssl下可以设置
//curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE, "PEM");
/* 客户端证书 */
curl_easy_setopt(curl, CURLOPT_SSLCERT, pCertFile);
/* 设置客户端证书的key和类型*/
curl_easy_setopt(curl, CURLOPT_SSLKEYTYPE, "PEM");
curl_easy_setopt(curl, CURLOPT_SSLKEY, pKeyName);
/* 验证服务器需要的根证书 */
curl_easy_setopt(curl, CURLOPT_CAINFO, pCACertFile);
/* 自签名证书不要验证对端 */
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, http_write);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &sRes);
/* 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));
} while (0);
/* always cleanup */
curl_easy_cleanup(curl);
}
std::cout<<"RESPONSE HTML:" << sRes;
return (res == CURLE_OK);
}
以上的代码如果根证书是受信任的,设置
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);
自签证书设置:
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
即可完成winssl的双向认证;