Is it possible to implement certificate pinning using the Win32 WinHTTP API, and if so how? I.e. how can I check the returned server certificate against a 'known good' one, preferably without having to permanently write the cert into the local certificate store.
Pinning is the process of associating a host with their expected X509 certificate or public key. Once a certificate or public key is known or seen for a host, the certificate or public key is associated or 'pinned' to the host.
Microsoft Windows HTTP Services (WinHTTP) supports Secure Sockets Layer (SSL) transactions including client certificates.
Securing your mobile applications ensures that you and your customers are safe. And unfortunately, just using SSL and HTTPS doesn't fully protect your data. Instead, certificate pinning currently tops the list of ways to make your application traffic secure.
(inspired by jww's answer)
Firstly I found this page to be excellent background reading about pinning and the choice between certificate and public key pinning.
I implemented certificate pinning using WinHTTP API as follows:
After WinHttpOpen but before WinHttpConnect, setup a callback for when requests are sent:
WinHttpSetStatusCallback(hSession, &callbackFunc, WINHTTP_CALLBACK_SENDING_REQUEST, NULL);
In the callback function, retrieve the raw certificate blob:
PCCERT_CONTEXT pCert=NULL;
DWORD dwSize=sizeof(pCert);
WinHttpQueryOption(hInternet, WINHTTP_OPTION_SERVER_CERT_CONTEXT, &pCert, &dwSize);
Then if doing full certificate pinning, compare sha1(pCert->pbCertEncoded)
against a known good certificate SHA1 thumbprint.
-Or- if doing public key pinning instead, compare sha1(pCert->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData)
against a known good SHA1 of a server public key.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With