web-dev-qa-db-ja.com

明示的なServicePointManager.SecurityProtocol呼び出しなしでは、TLS 1.2は.NET 4.7でネゴシエートされません

TLS 1.2のみをサポートするWebサイトでAPIの呼び出しをサポートするには、.NETアプリケーションをアップグレードする必要があります。私が読んだことから、アプリケーションが4.6以上をターゲットにしている場合、デフォルトでTLS 1.2を使用します。

テストするために、4.7を対象とするWindowsフォームアプリを作成しました。残念ながら、ServicePointManager.SecurityProtocolを明示的に設定しないとエラーになります。コードは次のとおりです。

HttpClient _client = new HttpClient();

var msg = new StringBuilder();

// If I uncomment the next line it works, but fails even with 4.7
// ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

var httpWebRequest = (HttpWebRequest)WebRequest.Create("https://sandbox.authorize.net");

httpWebRequest.KeepAlive = false;

try
{
    var httpWebResponse = (HttpWebResponse) httpWebRequest.GetResponse();

    msg.AppendLine("The HTTP request Headers for the first request are: ");

    foreach (var header in httpWebRequest.Headers)
    {
        msg.AppendLine(header.ToString());
    }

    ResponseTextBox.Text = msg.ToString();

}
catch (Exception exception)
{
   ResponseTextBox.Text = exception.Message;

   if (exception.InnerException != null)
   {
       ResponseTextBox.Text += Environment.NewLine + @"  ->" + exception.InnerException.Message;

       if (exception.InnerException.InnerException != null)
       {
            ResponseTextBox.Text += Environment.NewLine + @"     ->" + exception.InnerException.InnerException.Message;
       }
   }
}

次の行のコメントを外す場合:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

できます。これは、使用するTLSバージョンをハードコーディングしているため、良いソリューションではありません。したがって、将来はTLS 1.3を使用しません。

この行がなくても機能させるには、他に何をする必要がありますか。 4.7がインストールされたWindow 10マシンからテストしています。

更新

HttpClientでテストしてみたところ、同じ結果が得られました。SecurityProtocolを明示的に設定する必要がありました。

コード:

var msg = new StringBuilder();

// Need to uncomment code below for TLS 1.2 to be used
// ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

try
{
   var response = await _client.GetAsync(@"https://sandbox.authorize.net");

   msg.AppendLine("response.IsSuccessStatusCode : " + response.IsSuccessStatusCode);

   msg.AppendLine(await response.Content.ReadAsStringAsync());

   textBox.Text = msg.ToString();
  }

  catch (Exception exception)
  {
      textBox.Text = exception.Message;

      if (exception.InnerException != null)
      {
          textBox.Text += Environment.NewLine + @"  ->" + exception.InnerException.Message;
      }
   }
26
Josh

1つの解決策を見つけました。 .NET 4.7のWin10でTLS 1.2がデフォルトで使用されない理由に関する質問には答えませんが、ServicePointManager.SecurityProtocolを設定する必要はありません。

4.5.2と4.7のテストアプリの両方で機能したソリューションは、app.configに以下を追加することです。

<AppContextSwitchOverrides value="Switch.System.Net.DontEnableSchUseStrongCrypto=false"/>

ここでapp.config全体:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7"/>
    </startup>
    <runtime>
      <AppContextSwitchOverrides value="Switch.System.Net.DontEnableSchUseStrongCrypto=false"/>
    </runtime>
</configuration>
6
Josh

.NET Framework 4.7を対象とするアプリからは、ServicePointManager.SecurityProtocolプロパティのデフォルト値はSecurityProtocolTypeです。 SystemDefault

この変更により、SslStream(FTP、HTTPS、SMTPなど)に基づく.NET FrameworkネットワークAPIは、代わりにオペレーティングシステムからデフォルトのセキュリティプロトコルを継承できます。 .NET Frameworkで定義されたハードコードされた値を使用することの。

それがあなたが経験した新しい振る舞いと新しい設定の必要性の理由です:

<runtime>
   <AppContextSwitchOverrides value="Switch.System.ServiceModel.DisableUsingServicePointManagerSecurityProtocols=false;Switch.System.Net.DontEnableSchUseStrongCrypto=false" /> 
</runtime>

here および here を参照してください

14

Nick Yの答えの代替として、.NET 4.7+を使用するWindows 7では、Microsoft Secure Channel(Schannel)パッケージがTLS1.1およびTLS1.2を適切に送信するためにこれらのレジストリ設定を有効にする必要があることを発見しました。

これにより、.NETクライアントは引き続きSystem.Net.ServicePointManager.SecurityProtocolSystemDefaultに設定し、Windows 7コンピューターでTLS 1.1および1.2を取得します。

SystemDefaultオプションを使用すると、.NETはプロトコルの選択をOSに延期できます。これは、MicrosoftがOSのホッ​​トフィックスをリリースして安全でないプロトコルを無効にするか、ネイティブSCHANNELライブラリで新しいプロトコルのサポートを有効にすると、実行中の.NETフレームワークアプリがこの新しい動作を自動的に取得することを意味します。

レジストリエントリは次のとおりです。

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.1\Client]
"DisabledByDefault"=dword:00000000

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client]
"DisabledByDefault"=dword:00000000
7
MerickOWA

Windows 7および.NET 4.7.1を使用しています

Switch.System.ServiceModel.DisableUsingServicePointManagerSecurityProtocolsおよびSwitch.System.Net.DontEnableSchUseStrongCrypto他の2つの回答で言及されたものは私のプロジェクトでは機能せず、OPのコードも失敗していました。

ServicePointManagerおよびLocalAppContextSwitchesのソースコードを確認する別の 動作する設定

<runtime>
  <AppContextSwitchOverrides value="Switch.System.Net.DontEnableSystemDefaultTlsVersions=true" />
</runtime>
5
Nick Y

4.7.2を対象とするレガシーアプリで同じ問題が発生しました(Windows 10およびSSL3/TLSのみ...システムデフォルトではありません)。私の問題は、長年にわたるアップグレードプロセス中に、targetFrameworkを_system.web_> httpRuntime要素に追加しなかったことです(注:_system.web_> compilation要素)。大きなステップを踏む前に、system.webが次のようになっていることを確認してください。

_<system.web>
    <compilation targetFramework="4.7.2"></compilation>
    <httpRuntime targetFramework="4.7.2" />
</system.web>
_

上記の例では、現在使用しているフレームワークのバージョンが4.7以上であれば、4.7.2を交換します。

4
scottheckel