5

証明書または公開キーの固定をWindows 10 Universalアプリケーションに実装するには、適切な方法が必要です。すべてのコードはC#にあり、すべての接続はHTTPSなので、Windows.Web.Http.HttpClientクラスのものは素晴らしいでしょう。 X.509証明書などの秘密の詳細を知らない人が安全に行うことができる、このようなものを実装する方法については、簡単なクラス/ライブラリ、または少なくとも段階的なガイドがありますか?Windows 10ユニバーサルアプリケーションでの証明書ピン設定

ネイティブコードやOpenSSLのようなサードパーティのライブラリ(非常に複雑です)を使用したことについて、私が見つけたものがいくつかあります。私が見つけた最も良いことは、WP8.1とうまくいけばWin10で動作するはずのコードサンプルが含まれているWP8.0でピン設定することについてのthis questionですが、それは醜い混乱の種です。サーバーの証明書は、秘密情報で要求を送信するときに固定された証明書の1つであることを確認してください()。事前にチェックするのは、チェックの時間/使用時間(TOCTOU)攻撃のために安全ではないようです(ただし、HttpRequestMessageTransportInformation関数が接続を開いて開いているので、攻撃者が人を得るチャンスはありません新しい接続の中間の位置)。理想的には、HttpClientをフィルタリングして固定された証明書を持つサーバーに接続するだけですが、私が見つけることができるもっとも近いことは、HttpBaseProtocolFilter.IgnorableServerCertificateErrorsプロパティを使ってちょうど反対(特定の証明書エラーを無視して、約here)有効な証明書を制限するオプションがないようです。

誰にでも良い解決策がありますか? HttpRequestMessage.TransportInformation(カスタム証明書検証コード付き)アプローチが唯一のオプションである場合、TOCTOU攻撃に対して、リクエストを送信する前にそのプロパティをチェックするのは安全ですか?

+0

こんにちは、私はあなたと同じ問題を抱えています。 – toroveneno

答えて

-1

次の記事には良い解決策があります。それを試してみてください。

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

私はUWPには多くの経験を持っていないが、ウィンドウ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

HttpBaseProtocolFilterのServerCustomValidationRequestedイベントを見てきましたか?私にとっては難しい部分は、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。私はおそらく 'Windows.Security.Cryptography.Core.PersistedKeyProvider.OpenPublicKeyFromCertificate'を介して追加のナゲット参照なしでそれをしたいと思いますが、正しいバイト数を返すように正しい引数を取得できませんでした。誰かがより洗練された解決策を見つけることができれば、分かち合いましょう –

関連する問題