次のC#コードがあり、カスタム証明書を使用してhttps呼び出しを作成しています。 Tls 1.1を使用する場合、呼び出しは正常に機能します。 Tls 1.2を使用すると、通話が中断します。私はcurlを使用していますが、tls1.2を使用しても問題なく動作します。
C#コード:
X509Certificate2Collection collection = new X509Certificate2Collection();
collection.Import("C:\\SomePath\\MyCertificate.pfx", "MyPassword", X509KeyStorageFlags.PersistKeySet);
var cert = collection[0];
ServicePointManager.SecurityProtocol = ...;
ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, errors) => true;
HttpClientHandler handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback = (message, certificate2, arg3, arg4) => true;
handler.ClientCertificates.Add(cert);
var content = new ByteArrayContent(Encoding.GetEncoding("latin1").GetBytes("Hello world"));
HttpClient client = new HttpClient(handler);
var resp = client.PostAsync(requestUri: url, content: content).Result.Content.ReadAsStringAsync().Result;
で動作します:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11;
エラー:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
.Netエラーメッセージ:SocketException:既存の接続がリモートホストによって強制的に閉じられました
.Netバージョン:4.7.1
OS:Windows 10バージョン1703(サポートされている暗号リスト: https://msdn.Microsoft.com/en-us/library/windows/desktop/mt808163(v = vs.85).aspx )-サーバーは、サポートされている暗号の1つであるTLS_RSA_WITH_AES_256_GCM_SHA384を使用するように指定します。
Wiresharkでは、動作中の呼び出し(C#/ Tls1.1およびCurlTls 1.2)で、証明書がサーバーに送信されていることがわかります。 C#tls1.1呼び出しのwiresharkダンプは次のとおりです。
ただし、wiresharkでも、C#/ Tls 1.2では、クライアントからサーバーに証明書が送信されていないことがわかります。 C#tls1.2呼び出しのwiresharkダンプは次のとおりです。
誰かが私がここで欠けているものを見ることができますか?
[〜#〜]更新[〜#〜]
証明書には、tls1.2と組み合わせたWindowsのSchannelでサポートされていないmd5署名があるようです。ベンダーは、ソリューションとして別の証明書を作成しました。
この問題について説明しているこのランダムなスレッドに出くわしました: https://community.qualys.com/thread/15498
この問題の根本的な原因は正しいです。デフォルトでは、schannelベースのクライアントはSHA1、SHA256、SHA384、およびSHA512(Win10/Server 2016)を提供します。したがって、TLS 1.2サーバーは、MD5証明書をこれらのクライアントに送信することは想定されていません。
クライアント(HttpClient)はsignature_algorithms拡張機能にMD5をリストしないため、TLS1.2ハンドシェイクは失敗します。修正は、安全なサーバー証明書を使用することです。
ハンドラーのSslProtocols
プロパティを指定するべきではありませんか?
hander
定義の後に次の行を追加してみてください。
handler.SslProtocols = SslProtocols.Tls12;
このコードは、常に盲目的にtrueを返すことで、ある種の証明書エラーを隠していると思います。
handler.ServerCertificateCustomValidationCallback = (message, certificate2, arg3, arg4) => true;
Arg4の結果を真に分析する機能があることをお勧めします。それがSSLポリシーエラーです。それらを記録し、あなたはあなたの答えを得るでしょう。私の例では、コンソールに書き込みますが、トレースまたはファイルに書き込むことができます。 SslPolicyErrors列挙の値に関連付けられる番号を取得します。結果に基づいて、チェーンであるarg3をチェックする必要があるかもしれません。
ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => {
SslPolicyErrors errs = sslPolicyErrors;
Console.WriteLine("Policy Errors " + sslPolicyErrors.ToString());
return true;};