使用WinInet的客户端身份验证(证书+私钥)

时间:2019-03-22 10:47:01

标签: c++ ssl winapi https wininet

  • 这是我的previous question(关于WinHttp)的演变。
  • 我希望这是正确的方法...

我正在尝试使用WinInet(通过Win32 API)在与服务器的https中进行通信。

这是一个非常简单的代码:

HINTERNET ses = InternetOpen("test",INTERNET_OPEN_TYPE_DIRECT,NULL,NULL,0) ;
HINTERNET con = InternetOpenUrl( ses,"https://stackoverflow.com",NULL,0,0,0 ) ;
DWORD read ;
char  str [3000] ;
InternetReadFile( con,reinterpret_cast<void*>( str ),sizeof( str )-1,&read ) ;
str[read] = 0 ;
cout << &str[0] ;
InternetCloseHandle( con ) ;
InternetCloseHandle( ses ) ;

只要我与“经典” https服务器(例如stackoverflow.com)进行通信,一切都会顺利进行。问题是当我尝试与请求客户端身份验证的服务器通信时。

我有3个.pem文件:客户端的证书和私钥,以及用于验证客户端证书的根证书(即长度为2的证书链)。

有关信息,我可以使用以下cULR命令行连接服务器:

curl https://my.server --cert Client_cert.pem --key Client_key.pem --cacert Root_cert.pem

这是可能的证明!

在阅读WinInet文档时,我发现了一个名为“ Handling Authentication”的页面,但这全都与用户名:密码有关,与证书无关。

我发现我必须使用Crypt32库:我必须使用CertCreateCertificateContext创建一个证书上下文,然后将其插入证书存储区,然后使用该存储区进行连接... 好吧,我必须承认,我将很高兴找到一个不错的教程或一些代码示例! 顺便说一下,我对如何将我的私钥插入这些东西一无所知……

谢谢!

1 个答案:

答案 0 :(得分:0)

您必须使用INTERNET_OPTION_CLIENT_CERT_CONTEXT并调用InternetSetOption()将证书传递给WinInet:

  

INTERNET_OPTION_CLIENT_CERT_CONTEXT

     

84

     

InternetQueryOption不支持此标志。 lpBuffer   参数必须是指向CERT_CONTEXT结构的指针,而不是   指向CERT_CONTEXT指针的指针。如果申请收到   ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED,它必须调用InternetErrorDlg   或使用InternetSetOption提供证书,然后重试   请求。然后调用CertDuplicateCertificateContext,以便   传递的证书上下文可以由   应用。

例如,

InternetSetOption(hI,INTERNET_OPTION_CLIENT_CERT_CONTEXT,(void*)cert,sizeof(CERT_CONTEXT));

顺便说一句,curl调用不是很好的例子,因为curl使用libcurl,它使用OpenSSL。