3

When attempting a web request to a site which requires TLS 1.3 https://shop.claytonengineering.com/. I'm receiving the following exception on "request.GetResponse();".

Exception: The SSL connection could not be established, see inner exception. Inner Exception: The client and server cannot communicate, because they do not possess a common algorithm.

From Google Chrome Developer tools Security tab - "The connection to this site is encrypted and authenticated using TLS 1.3, X25519, and AES_128_GCM."

Any ideas on how to get this request to work?

HttpWebResponse response = null;

HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://shop.claytonengineering.com/");

request.KeepAlive = true;
request.Headers.Add("Upgrade-Insecure-Requests", @"1");
request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36";
request.Headers.Add("Sec-Fetch-Mode", @"navigate");
request.Headers.Add("Sec-Fetch-User", @"?1");
request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3";
request.Headers.Add("Sec-Fetch-Site", @"same-origin");

request.Headers.Set(HttpRequestHeader.AcceptEncoding, "gzip, deflate, br");
request.Headers.Set(HttpRequestHeader.AcceptLanguage, "en-US,en;q=0.9");

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls13;

response = (HttpWebResponse)request.GetResponse();

string html = null;

using (StreamReader stream = new StreamReader(response.GetResponseStream(), Encoding.UTF8))
{
    html = stream.ReadToEnd();
}
Jay Metro
  • 31
  • 1
  • 2

2 Answers2

3

There are at least two parts to a successful TLS connection:

  1. Protocol version
  2. Ciphersuite match

In both cases both the client and server must match up to use the same protocol and cipher. You already understand that there are multiple TLS versions (1.0, 1.1, 1.2, 1.3) but there are also multiple ciphers that are used to encrypt/decrypt information.

After the 3-way handshake, the client sends its accepted versions in the "Client Hello" and a list of accepted ciphers to the server. The server finds a match and sends that information back to the client ("Server Hello"), then communication begins.

In this case, although you're both using TLS 1.3, you aren't matching up with a cipher. The server has a list of ciphers that can be found by using the test found at ssllabs.com.

The list of ciphers accepted by the server you listed above is in the image below. You can enable one of the above on your client and then the connection should succeed. I assume you're using Windows, so please see this:

https://www.howtogeek.com/221080/how-to-update-your-windows-server-cipher-suite-for-better-security/#:~:text=On%20the%20left%20hand%20side%2C%20expand%20Computer%20Configuration%2C,%E2%80%9CEnabled%E2%80%9D%20button%20to%20edit%20your%20server%E2%80%99s%20Cipher%20Suites.

enter image description here

Matt Small
  • 2,182
  • 1
  • 10
  • 16
  • 1
    Confirm Windows 10 Pro - 10.0.19043 I also confirmed the following ciphers are installed on the client. Which are the first two listed on the server cipher list. After setting these as the first two in the cipher suite order, the web request still fails with the same exception (no surprise). TLS_AES_128_GCM_SHA256,TLS_AES_256_GCM_SHA384 Seems to me like there is a bug with the .NET framework. Any thoughts? – Jay Metro Nov 17 '21 at 21:03
  • A network trace (wireshark) will tell you what the client is sending. I don't think this is a bug in the .NET framework. This code has been in production for years. – Matt Small Nov 17 '21 at 22:04
1

I had this very same issue and found out that while .Net framework 4.8 and .Net5.0 and 6.0 all have implementations of the TLS1.3 stack, none of them seem to use them when you do not tell Windows to do so.

In my case I had to add the following registry key:

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.3]

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

For some reason these are not there by default.

Kalix
  • 39
  • 3