简体   繁体   中英

Adding Cipher suite to TLS1.2 of HttpClient of dotnetcore 3.1

I encounter the folowing exception when connecting to the website of Western digital:

website of Western digital

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 ---

I think that the C# code is correct as I have 3/4 Unit test Passing:

        [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")]

单元测试通过

The SSL diagnostic done by ssllabs gives a list of supported cipher suites handled by the website of Western digital: 诊断

Firefox connects succesfully to the website, and Wireshark spots that firefox has 1 cipher in the list: 火狐密码列表

However my dotnet core application has a fatal in the ssl handshake because it has not a single cipher common with WD:

点网密码套件

I took a lot of time to understand that the error comes from here.... if it really comes from here.

Hence 2 questions comes from this analysis:

  • Is it possible to add a cipher suite in my dot net core 3.1 application, written in C# to be compliant with this website? I have seen discussion on internet stipulating that maybe the Us company which is Microsoft is not allowed to export strong cryptographic algorithms... if this is true, what about firefox (Usa too) using the same suite as Western digital (Usa too).

  • Is there a possibility to use in C# another library ( I think about open SSl) but the other library does provide all layers of https (ie propose equivalent of httpClient) / what about crossplatform to avoid loosing the cross platform feature of dotnetcore....

Remark: Even Fiddler has this problem: Which is understandable as it is also relying on the dot net framework technology: 提琴手握手

  • To answer comment of @Steffen Ullrich I run this stuff on Win7: 视窗版本

.NET Core uses the ciphers supported by the native TLS stack, ie SChannel. Which ciphers are supported depend on the version of Windows. Which ciphers are supported by your OS (is documented in TLS Cipher Suites in Windows 7 . As you can see, none of the ciphers offered by the server are supported by your OS.

With Firefox or Chrome browser the situation is different. These come with their own stack and are thus not limited on what the OS offers. That's why they work.

I had the same issue, my autotests (dotnetcore3.1) are run on the WS 2012 R2 machines and I have to call third-party API which accepts only TWO cipher suites: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f) TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030).

C# HttpClient relies on cipher suites in the host system, in contrast to Chrome, Firefox, and Curl which have their own Security and Cryptography systems. WS 2012 R2 doesn't have those two ciphers and I know no way how to add them to the machines, there are no windows updates with those ciphers.

I've chosen using a pretty cool NuGet packet CurlThin as the solution. Using it we can set up our own cipher suites for requests, so we need to do nothing with the server side.

I've installed two packets: CurlThin itself and CurlThin.Native .
The resulting code for a GET request with a header, to an HTTPS endpoint, looks like this:

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;
}

Indeed the same code PASS succefully when executed on Windows 10: 赢得 10 名执行官

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM