在 dotnet core 3.1 中将密码套件添加到 HttpClient 的 TLS1.2
Adding Cipher suite to TLS1.2 of HttpClient of dotnetcore 3.1
连接西数网站出现如下异常:
22:02:34,803 | HttpGrabber | DEBUG | Grabbing: GET https://shop.westerndigital.com/de-de/products/internal-drives/wd-red-sata-2-5-ssd#WDS200T1R0A
22:02:34,858 | HttpGrabber | DEBUG | System.Net.Http.SocketsHttpHandler.Http2Support: True
22:02:34,865 | HttpGrabber | DEBUG | System.Net.Http.UseSocketsHttpHandler: True
22:02:35,067 | HttpGrabber | ERROR | System.AggregateException: One or more errors occurred. (The SSL connection could not be established, see inner exception.)
---> System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception.
---> System.Security.Authentication.AuthenticationException: Authentication failed, see inner exception.
---> System.ComponentModel.Win32Exception (0x80090326): Le message reçu était inattendu ou formaté de façon incorrecte.
--- End of inner exception stack trace ---
我认为 C# 代码是正确的,因为我有 3/4 单元测试通过:
[TestCase("https://allianz-fonds.webfg.net/sheet/fund/FR0013192572/730?date_entree=2018-04-04")]
[TestCase("https://www.galaxus.de/de/s1/product/zotac-zbox-magnus-en72070v-intel-core-i7-9750h-0gb-pc-13590721")]
[TestCase("https://www.hystou.com/Gaming-Mini-PC-F7-with-Nvidia-GeForce-GTX-1650-p177717.html")]
[TestCase("https://shop.westerndigital.com/de-de/products/internal-drives/wd-red-sata-2-5-ssd#WDS200T1R0A")]
ssllabs做的SSL诊断给出了Western Digital网站处理的支持的密码套件列表:
Firefox 成功连接到网站,Wireshark 发现 firefox 在列表中有 1 个密码:
但是我的 dotnet 核心应用程序在 ssl 握手中有一个致命问题,因为它没有一个与 WD 通用的密码:
我花了很多时间才明白错误来自这里....如果它真的来自这里。
因此分析得出 2 个问题:
是否可以在我的 dot net core 3.1 应用程序中添加一个密码套件,用 C# 编写以符合该网站?
我在互联网上看到过讨论,规定可能不允许微软这家美国公司出口强加密算法……如果这是真的,那么 firefox(也是美国)使用与 Western Digital(也是美国)相同的套件呢?
是否有可能在 C# 中使用另一个库(我考虑开放 SSl),但另一个库确实提供了 https 的所有层(即建议等效于 httpClient)/如何避免跨平台失去 dotnetcore 的跨平台特性....
备注:连Fiddler都有这个问题!这是可以理解的,因为它也依赖于 dot net 框架技术:
- 回答@Steffen Ullrich 的评论我 运行 在 Win7 上的这些东西:
.NET Core 使用本机 TLS 堆栈支持的密码,即 SChannel。支持哪些密码取决于 Windows 的版本。您的 OS 支持哪些密码(记录在 TLS Cipher Suites in Windows 7 中。如您所见,服务器提供的密码中 none 受您的 OS 支持。
使用 Firefox 或 Chrome 浏览器时情况有所不同。它们带有自己的堆栈,因此不受 OS 提供的限制。这就是它们起作用的原因。
确实相同的代码在 Windows 10 上执行时成功通过:
我遇到了同样的问题,我的自动测试 (dotnetcore3.1) 在 WS 2012 R2 机器上是 运行,我必须调用 third-party API,它只接受两个密码套房:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030).
C# HttpClient 依赖主机系统中的密码套件,与 Chrome、Firefox 和 Curl 相比,后者拥有自己的安全和密码系统。 WS 2012 R2 没有这两个密码,我不知道如何将它们添加到机器上,这些密码没有 windows 更新。
我选择使用非常酷的 NuGet 数据包 CurlThin 作为解决方案。使用它我们可以为请求设置我们自己的密码套件,所以我们不需要对服务器端做任何事情。
我安装了两个数据包:CurlThin 本身和 CurlThin.Native.
使用 header 到 HTTPS 端点的 GET 请求的结果代码如下所示:
using CurlThin;
using CurlThin.Enums;
using CurlThin.Helpers;
using CurlThin.Native;
using CurlThin.SafeHandles;
using System.Text;
private static string GetToken()
{
//This string is for extracting libcurl and ssl libs to the bin directory.
CurlResources.Init();
var global = CurlNative.Init();
var easy = CurlNative.Easy.Init();
string content;
try
{
var dataCopier = new DataCallbackCopier();
CurlNative.Easy.SetOpt(easy, CURLoption.URL, "https://someendpoints.net/thatendpoint?fake=true");
CurlNative.Easy.SetOpt(easy, CURLoption.WRITEFUNCTION, dataCopier.DataHandler);
//This string is needed when you call a https endpoint.
CurlNative.Easy.SetOpt(easy, CURLoption.CAINFO, CurlResources.CaBundlePath);
var headers = CurlNative.Slist.Append(SafeSlistHandle.Null, "Authorization: Bearer blablabla");
CurlNative.Easy.SetOpt(easy, CURLoption.HTTPHEADER, headers.DangerousGetHandle());
//Your set of ciphers, full list is here https://curl.se/docs/ssl-ciphers.html
CurlNative.Easy.SetOpt(easy, CURLoption.SSL_CIPHER_LIST, "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256");
CurlNative.Easy.Perform(easy);
content = Encoding.UTF8.GetString(dataCopier.Stream.ToArray());
}
finally
{
easy.Dispose();
if (global == CURLcode.OK)
CurlNative.Cleanup();
}
return content;
}
连接西数网站出现如下异常:
22:02:34,803 | HttpGrabber | DEBUG | Grabbing: GET https://shop.westerndigital.com/de-de/products/internal-drives/wd-red-sata-2-5-ssd#WDS200T1R0A
22:02:34,858 | HttpGrabber | DEBUG | System.Net.Http.SocketsHttpHandler.Http2Support: True
22:02:34,865 | HttpGrabber | DEBUG | System.Net.Http.UseSocketsHttpHandler: True
22:02:35,067 | HttpGrabber | ERROR | System.AggregateException: One or more errors occurred. (The SSL connection could not be established, see inner exception.)
---> System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception.
---> System.Security.Authentication.AuthenticationException: Authentication failed, see inner exception.
---> System.ComponentModel.Win32Exception (0x80090326): Le message reçu était inattendu ou formaté de façon incorrecte.
--- End of inner exception stack trace ---
我认为 C# 代码是正确的,因为我有 3/4 单元测试通过:
[TestCase("https://allianz-fonds.webfg.net/sheet/fund/FR0013192572/730?date_entree=2018-04-04")]
[TestCase("https://www.galaxus.de/de/s1/product/zotac-zbox-magnus-en72070v-intel-core-i7-9750h-0gb-pc-13590721")]
[TestCase("https://www.hystou.com/Gaming-Mini-PC-F7-with-Nvidia-GeForce-GTX-1650-p177717.html")]
[TestCase("https://shop.westerndigital.com/de-de/products/internal-drives/wd-red-sata-2-5-ssd#WDS200T1R0A")]
ssllabs做的SSL诊断给出了Western Digital网站处理的支持的密码套件列表:
Firefox 成功连接到网站,Wireshark 发现 firefox 在列表中有 1 个密码:
但是我的 dotnet 核心应用程序在 ssl 握手中有一个致命问题,因为它没有一个与 WD 通用的密码:
我花了很多时间才明白错误来自这里....如果它真的来自这里。
因此分析得出 2 个问题:
是否可以在我的 dot net core 3.1 应用程序中添加一个密码套件,用 C# 编写以符合该网站? 我在互联网上看到过讨论,规定可能不允许微软这家美国公司出口强加密算法……如果这是真的,那么 firefox(也是美国)使用与 Western Digital(也是美国)相同的套件呢?
是否有可能在 C# 中使用另一个库(我考虑开放 SSl),但另一个库确实提供了 https 的所有层(即建议等效于 httpClient)/如何避免跨平台失去 dotnetcore 的跨平台特性....
备注:连Fiddler都有这个问题!这是可以理解的,因为它也依赖于 dot net 框架技术:
- 回答@Steffen Ullrich 的评论我 运行 在 Win7 上的这些东西:
.NET Core 使用本机 TLS 堆栈支持的密码,即 SChannel。支持哪些密码取决于 Windows 的版本。您的 OS 支持哪些密码(记录在 TLS Cipher Suites in Windows 7 中。如您所见,服务器提供的密码中 none 受您的 OS 支持。
使用 Firefox 或 Chrome 浏览器时情况有所不同。它们带有自己的堆栈,因此不受 OS 提供的限制。这就是它们起作用的原因。
确实相同的代码在 Windows 10 上执行时成功通过:
我遇到了同样的问题,我的自动测试 (dotnetcore3.1) 在 WS 2012 R2 机器上是 运行,我必须调用 third-party API,它只接受两个密码套房:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f) TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030).
C# HttpClient 依赖主机系统中的密码套件,与 Chrome、Firefox 和 Curl 相比,后者拥有自己的安全和密码系统。 WS 2012 R2 没有这两个密码,我不知道如何将它们添加到机器上,这些密码没有 windows 更新。
我选择使用非常酷的 NuGet 数据包 CurlThin 作为解决方案。使用它我们可以为请求设置我们自己的密码套件,所以我们不需要对服务器端做任何事情。
我安装了两个数据包:CurlThin 本身和 CurlThin.Native.
使用 header 到 HTTPS 端点的 GET 请求的结果代码如下所示:
using CurlThin;
using CurlThin.Enums;
using CurlThin.Helpers;
using CurlThin.Native;
using CurlThin.SafeHandles;
using System.Text;
private static string GetToken()
{
//This string is for extracting libcurl and ssl libs to the bin directory.
CurlResources.Init();
var global = CurlNative.Init();
var easy = CurlNative.Easy.Init();
string content;
try
{
var dataCopier = new DataCallbackCopier();
CurlNative.Easy.SetOpt(easy, CURLoption.URL, "https://someendpoints.net/thatendpoint?fake=true");
CurlNative.Easy.SetOpt(easy, CURLoption.WRITEFUNCTION, dataCopier.DataHandler);
//This string is needed when you call a https endpoint.
CurlNative.Easy.SetOpt(easy, CURLoption.CAINFO, CurlResources.CaBundlePath);
var headers = CurlNative.Slist.Append(SafeSlistHandle.Null, "Authorization: Bearer blablabla");
CurlNative.Easy.SetOpt(easy, CURLoption.HTTPHEADER, headers.DangerousGetHandle());
//Your set of ciphers, full list is here https://curl.se/docs/ssl-ciphers.html
CurlNative.Easy.SetOpt(easy, CURLoption.SSL_CIPHER_LIST, "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256");
CurlNative.Easy.Perform(easy);
content = Encoding.UTF8.GetString(dataCopier.Stream.ToArray());
}
finally
{
easy.Dispose();
if (global == CURLcode.OK)
CurlNative.Cleanup();
}
return content;
}