I need a good way to implement certificate or public-key pinning in a Windows 10 Universal application. All the code is in C#, and all connections are HTTPS, so something for the Windows.Web.Http.HttpClient
class would be great. Is there a simple class/library, or at least a step-by-step guide, for how to implement this stuff that can be done safely by somebody who doesn't know the arcane details of X.509 certificates and so on?
Some things I've found talk about using native code, or third-party libraries like OpenSSL (very complicated!). The best thing I've found is this question about pinning in WP8.0, which includes a code sample that should work on WP8.1 and hopefully also Win10, but it's kind of ugly and confusing, and I'm not sure how to require that the server's certificate is one of the pinned ones when sending the request with the sensitive information. Checking beforehand doesn't seem safe because of time-of-check/time-of-use (TOCTOU) attacks (unless the HttpRequestMessage
.TransportInformation
function opens the connection and then holds it open so there's no chance for an attacker to gain a man-in-the-middle position on a new connection). Ideally there'd be a way to filter the HttpClient so it only connects to servers with pinned certs, but the closest thing I can find to that does exactly the opposite (ignore certain cert errors, as talked about here) via the HttpBaseProtocolFilter.IgnorableServerCertificateErrors
property, which doesn't seem to have any option to restrict the valid certificates.
Does anybody have a good solution here? If the HttpRequestMessage.TransportInformation
approach (with custom cert validation code) is the only option, is it safe against TOCTOU attacks to check that property before sending the request?