Pin a certificate in a Windows 10 Universal application

I need a good way to implement a certificate or public key in a universal Windows 10 application. All 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 on how to implement this material that can be done safely by someone who does not know the secret details of X.509 certificates, etc.?

Some of the things I found talk about using native code or third-party libraries such as OpenSSL (very complicated!). The best I found was this pinning question in WP8.0, which includes sample code 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 so that the server certificate is one of the secured when sending a request with confidential information. Checking in advance does not seem secure due to attacks over time / time of use (TOCTOU) (unless the HttpRequestMessage . TransportInformation function opens the connection and then keeps it open, so there is no way for an attacker to get a person in the middle of the position on a new connection). Ideally, there would be a HttpClient filtering method, so it would only connect to servers with pinned certificates, but the closest I can find to this does the exact opposite (ignore some certificate errors mentioned here ) through the HttpBaseProtocolFilter.IgnorableServerCertificateErrors property. which does not seem to be able to restrict valid certificates.

Does anyone have a good solution? If the HttpRequestMessage.TransportInformation approach (with a custom certificate verification code) is the only option, is it safe to check this property against TOCTOU attacks before sending a request?

+5
source share
2 answers

Have you watched the ServerCustomValidationRequested event with an HttpBaseProtocolFilter? The tricky part for me was extracting the public certificate from the Certificate object. To do this, I had to bring the System.Security.Cryptography.X509Certificates nuget package. My code is as follows:

 private void DoIt() { using (var filter = new HttpBaseProtocolFilter()) { filter.ServerCustomValidationRequested += FilterOnServerCustomValidationRequested; var httpClient = new Windows.Web.Http.HttpClient(filter); var myString = await httpClient.GetStringAsync(new Uri("https://myserver.com")); // I guess we should be kind and unsubscribe? filter.ServerCustomValidationRequested -= FilterOnServerCustomValidationRequested; } } private void FilterOnServerCustomValidationRequested(HttpBaseProtocolFilter sender, HttpServerCustomValidationRequestedEventArgs args) { if (!IsCertificateValid(args.RequestMessage, args.ServerCertificate, args.ServerCertificateErrors)) { args.Reject(); } } private bool IsCertificateValid(Windows.Web.Http.HttpRequestMessage httpRequestMessage, Certificate cert, IReadOnlyList<ChainValidationResult> sslPolicyErrors) { // disallow self-signed certificates or certificates with errors if (sslPolicyErrors.Count > 0) { return false; } if (RequestRequiresCheck(httpRequestMessage.RequestUri)) { var certificateSubject = cert?.Subject; bool subjectMatches = certificateSubject == CERTIFICATE_COMMON_NAME; var certArray = cert?.GetCertificateBlob().ToArray(); var x509Certificate2 = new X509Certificate2(certArray); var certificatePublicKey = x509Certificate2.GetPublicKey(); var certificatePublicKeyString = Convert.ToBase64String(certificatePublicKey); bool publicKeyMatches = certificatePublicKeyString == CERTIFICATE_PUBLIC_KEY; return subjectMatches && publicKeyMatches; } return true; } private bool RequestRequiresCheck(Uri uri) { return uri.IsAbsoluteUri && uri.AbsoluteUri.StartsWith("https://", StringComparison.CurrentCultureIgnoreCase) && uri.AbsoluteUri.StartsWith(BASE_URL, StringComparison.CurrentCultureIgnoreCase); } 
+1
source

The following article has a good solution. Give it a try.

https://www.codeproject.com/Articles/849510/Certificate-Pinning-on-Windows-Phone

I don’t have much experience in UWP, but in Window 8.1 storage applications there is a package.appxmanifest file that allows you to define your root certificates on the Declaration tab, so you can do the correct verification in the code.

The following article also has some good ways to determine how to secure applications and HTTP connections. https://blogs.windows.com/buildingapps/2015/10/13/create-more-secure-apps-with-less-effort-10-by-10/#bWSeoR0pMyW2H8fg.97

-1
source

Source: https://habr.com/ru/post/1240126/


All Articles