Signing a certificate using the WinHTTP API
(inspired by jww's answer)
First, I found this page to be an excellent background read about pinning and choosing between certificate and public key disclosure.
I have implemented certificate binding using WinHTTP API as follows:
-
After WinHttpOpen, but before WinHttpConnect, set up a callback to send requests:
WinHttpSetStatusCallback(hSession, &callbackFunc, WINHTTP_CALLBACK_SENDING_REQUEST, NULL);
-
In the callback function, retrieve the raw blob certificate:
PCCERT_CONTEXT pCert=NULL; DWORD dwSize=sizeof(pCert); WinHttpQueryOption(hInternet, WINHTTP_OPTION_SERVER_CERT_CONTEXT, &pCert, &dwSize);
-
Then, if you are doing full certificate pinning, compare
sha1(pCert->pbCertEncoded)
with a well-known SHA1 fingerprint with a good certificate. -
-Or- if using public key bindings instead, compare
sha1(pCert->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData)
with the known good SHA1 of the server public key.
source to share
Is it possible to implement certificate pinning using the Win32 WinHTTP API, and if so, how?
It looks like you can attach a certificate. You can set the callback with WINHTTP_STATUS_CALLBACK
. When the callback is called with WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER
, you can verify the certificate with WinHttpQueryOption
and WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT
. The server certificate is returned in the structure WINHTTP_CERTIFICATE_INFO
.
There the SSL in WinHTTP page has more information.
... without having to constantly write the certificate to the local certificate store.
The certificate store issue is another authority that might require you to certify the site you are connecting to. In this case, the real trusted authority doesn't even have to be in the store to get pwn'd. This is one of the [obvious] problems with the Web Application / Browser Model and CA Zoo.
source to share