5

Мне нужен хороший способ внедрения сертификата или открытого ключа в универсальном приложении Windows 10. Весь код находится в C#, и все соединения HTTPS, поэтому что-то для класса Windows.Web.Http.HttpClient было бы замечательно. Есть ли простой класс/библиотека или, по крайней мере, пошаговое руководство, как реализовать этот материал, который можно сделать безопасно кем-либо, кто не знает тайных деталей сертификатов X.509 и т. Д.?Сертификат, прикрепленный к Windows 10 Универсальное приложение

Некоторые вещи, которые я нашел, говорят об использовании собственного кода или сторонних библиотек, таких как OpenSSL (очень сложно!). Самое лучшее, что я нашел, это this question о pinning в WP8.0, который включает в себя образец кода, который должен работать на WP8.1, и, надеюсь, также Win10, но это отвратительно и запутанно, и я не уверен, как требовать что сертификат сервера является одним из закрепленных при отправке запроса с конфиденциальной информацией. Проверка заранее не кажется безопасной из-за времени проверки/времени использования (TOCTOU) атак (если только функция HttpRequestMessage. TransportInformation не открывает соединение, а затем держит ее открытой, чтобы у человека не было шанса набрать человека - в-середине позиции на новом соединении). В идеале был бы способ фильтрации HttpClient, поэтому он будет подключаться только к серверам с прикрепленными сертификатами, но самое близкое, что я могу найти к этому, делает точно противоположное (игнорируйте некоторые ошибки сертификата, о которых говорилось около here) через свойство HttpBaseProtocolFilter.IgnorableServerCertificateErrors, который, как представляется, не имеет возможности ограничить действительные сертификаты.

У кого-нибудь есть хорошее решение здесь? Если подход HttpRequestMessage.TransportInformation (с пользовательским сертификатом проверки подлинности) является единственным вариантом, безопасно ли против атак TOCTOU проверять это свойство перед отправкой запроса?

+0

Привет, У меня такие же проблемы, как и вы, вам повезло, как это сделать? – toroveneno

ответ

-1

Следующая статья имеет хорошее решение. Попробуй.

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

У меня нет большого опыта в UWP но в Window 8.1 магазин приложений имеет package.appxmanifest файл, который позволит вам определить свои корневые сертификаты на «вкладке Декларация» так, на код, который вы можете сделать надлежащую проверку.

В следующей статье также есть несколько полезных способов определить, как защитить приложения и HTTP-соединения. https://blogs.windows.com/buildingapps/2015/10/13/create-more-secure-apps-with-less-effort-10-by-10/#bWSeoR0pMyW2H8fg.97

1

Вы изучили событие ServerCustomValidationRequested с HttpBaseProtocolFilter? Сложная часть для меня заключалась в извлечении публичного сертификата из объекта Certificate. Для этого мне пришлось принести пакет System.Security.Cryptography.X509Certificates nuget. Мой код выглядит так:

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); 
} 
+0

Кстати, я получил решение для извлечения открытого ключа здесь: https://stackoverflow.com/a/38126387/40783. Я бы хотел сделать это без дополнительной ссылки на nuget, может быть, с помощью 'Windows.Security.Cryptography.Core.PersistedKeyProvider.OpenPublicKeyFromCertificate', но я не смог получить правильные аргументы, чтобы заставить его работать и вернуть правильное количество байтов. Пожалуйста, поделитесь, если кто-то может найти более чистое решение. –