Reputation: 11200
I am on Windows 10 1903, and my IE and Chrome can access Tls 1.2 website without any special settings. But when I try to use my .net 4.7.2 application to access a web API which only allows Tls 1.2 connect, my connection got terminated by the server.
I have to add ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12;
in my code to allow my application to connect to that endpoint correctly.
But after doing some research, I found from this document that for .Net 4.7 and above the default value for ServicePointManager.SecurityProtocol
should be SecurityProtocolType.SystemDefault
and according to this document the Tls 1.2 protocal is enable by default.
So I traced my code and found that the default value for ServicePointManager.SecurityProtocol
on my system is System.Net.SecurityProtocolType.Ssl3 | System.Net.SecurityProtocolType.Tls
. What's more crazy, when I set the protocol to SecurityProtocolType.SystemDefault
, I got this error:
System.Net.Http.HttpRequestException : An error occurred while sending the request.
---- System.Net.WebException : The underlying connection was closed: An unexpected error occurred on a receive.
-------- System.ArgumentException : The specified value is not valid in the 'SslProtocolType' enumeration.
Parameter name: sslProtocolType
I checked my system registry and IE settings, and nothing overrides or disables Tls 1.2.
So I am very confused and wonder if is there something wrong with my system or with my code.
Upvotes: 19
Views: 20339
Reputation: 4926
Was this problem when debugging in Visual Studio 2015? If so, the answer is likely because you have 'Enable the Visual Studio hosting process' turned on (the default).
The vshost.exe generated by VS 2015 incorrectly has TargetFramework=4.5 set in its metadata. Even though you are running in Framework 4.7, .NET honours the TargetFramework and sets ServicePointManager.SecurityProtocol to Ssl3|Tls.
Your real .exe will have the correct TargetFramework metadata. When you run it SecurityProtocol will be set to SystemDefault.
It's a bug in VS 2015 that never got fixed. You can turn off the VS hosting process in project properties. The vshost process doesn't exist in VS 2017 and later.
Upvotes: 1
Reputation: 71
With .NET 4.6 installed you still must put in a registry key to have .NET programs compiled for earlier versions to use strong cryptography. Once this is set, all .NET code will use the newer TLS protocols-
64 bit
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319]
"SchUseStrongCrypto"=dword:00000001
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v4.0.30319]
"SchUseStrongCrypto"=dword:00000001
32 bit
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319]
"SchUseStrongCrypto"=dword:00000001
.NET programs compiled for 4.6 framework and higher will act as if the key is there. The ServiceEndpointManager.SecurityProtocol setting can be used to specify it explicitly so it will be used even w/o the registry.
Upvotes: 5
Reputation: 38152
You will get this error if the app you're running targets a .NET framework earlier than 4.6 (even if you are actually running it on a newer .NET FX). You can check this by examining the value of AppDomain.CurrentDomain.SetupInformation.TargetFrameworkName
.
Specifically, this will get thrown in such a case where the SystemDefaultTlsVersions registry value is not set to 1
:
https://referencesource.microsoft.com/#System/net/System/Net/SecureProtocols/_SslState.cs,164
AppContext switches won't help you either, as they only take effect for framework versions starting from 4.6. Assuming you can't change the targeted .NET version (example) and you don't want to force your users to change their registry settings, I recommend code like this:
if (ServicePointManager.SecurityProtocol != SecurityProtocolType.SystemDefault)
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
}
For more information: https://learn.microsoft.com/en-us/dotnet/framework/network-programming/tls
Upvotes: 12
Reputation: 1273
We ran into this at the office. My understanding is that the SystemDefault value comes from the Windows registry.
The DefaultSecureProtocols registry entry can be added in the following path:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\WinHttp
On x64-based computers, DefaultSecureProtocols must also be added to the Wow6432Node path:
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Internet Settings\WinHttp
The registry value is a DWORD bitmap. The value to use is determined by adding the values corresponding to the protocols desired.
DefaultSecureProtocols Value Protocol enabled
0x00000008 Enable SSL 2.0 by default
0x00000020 Enable SSL 3.0 by default
0x00000080 Enable TLS 1.0 by default
0x00000200 Enable TLS 1.1 by default
0x00000800 Enable TLS 1.2 by default
Upvotes: 1