ChatGPT解决这个技术问题 Extra ChatGPT

Default SecurityProtocol in .NET 4.5

What is the default security protocol for communicating with servers that support up to TLS 1.2? Will .NET by default, choose the highest security protocol supported on the server side or do I have to explicitly add this line of code:

System.Net.ServicePointManager.SecurityProtocol = 
SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;

Is there a way to change this default, besides a code change?

Lastly, does .NET 4.0 only support up to TLS 1.0? i.e. I have to upgrade client projects to 4.5 to support TLS 1.2.

My motivation is to remove support for SSLv3 on the client side even if server supports it (I already have a powershell script to disable this in the machine registry) and to support the highest TLS protocol that the server supports.

Update: Looking at the ServicePointManager class in .NET 4.0 I see no enumerated values for TLS 1.0 and 1.1. In both .NET 4.0/4.5, the default is SecurityProtocolType.Tls|SecurityProtocolType.Ssl3. Hopefully this default won't break by disabling SSLv3 in the registry.

However, I've decided I have to upgrade all apps to .NET 4.5 and to explicitly add SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; anyway to all bootstrapping code of all applications.

This will make outbound requests to various apis and services to not downgrade to SSLv3 and should select the highest level of TLS.

Does this approach sound reasonable or overkill? I have many applications to update, and I want to future proof them since I hear even TLS 1.0 may be deprecated in the near future by some providers.

As a client making outbound requests to APIs, does disabling SSL3 in the registry even have an effect in the .NET framework? I see by default, TLS 1.1 and 1.2 are not enabled, do we have to enable it via the registry? RE http://support.microsoft.com/kb/245030.

After a bit of investigation, I believe the registry settings will have no affect since they apply to IIS (server subkey) and browsers (client subkey).

Sorry this post turned into multiple questions, followed up with "maybe" answers.

For those who want to see the best answer for this, sort by votes!
Related SO Q&A: stackoverflow.com/questions/41618766/… Readers should note this question is aging and newer recommendations are in place as of 2020.

S
Scott

Some of the those leaving comments on other answers have noted that setting System.Net.ServicePointManager.SecurityProtocol to specific values means that your app won't be able to take advantage of future TLS versions that may become the default values in future updates to .NET. Instead of specifying a fixed list of protocols, do the following:

For .NET 4.7 or later, do not set System.Net.ServicePointManager.SecurityProtocol. The default value (SecurityProtocolType.SystemDefault) will allow the operating system to use whatever versions it knows and has been configured for, including any new versions that may not have existed at the time the app was created.

For earlier versions of .NET Framework, you can instead turn on or off protocols you know and care about, leaving any others as they are.

To turn on TLS 1.1 and 1.2 without affecting other protocols:

System.Net.ServicePointManager.SecurityProtocol |= 
    SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;

Notice the use of |= to turn on these flags without turning others off.

To turn off SSL3 without affecting other protocols:

System.Net.ServicePointManager.SecurityProtocol &= ~SecurityProtocolType.Ssl3;

This is the really the correct answer. The accepted answer will ensure that your app will always toggle off new TLS versions unless you go back and update your code.
@Gertsen No, it's a bitwise or, so it just turns the appropriate bits on if they're off. If those bits are already on, no change occurs.
And the PowerShell equivalent of this is [Net.ServicePointManager]::SecurityProtocol = ([Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls12) Invoke-RestMethod relies on the same underlying .NET framework libraries.
Since nobody is talking about where to put this code, I successfully put it into Application_Start of Global.asax.cs for my ASP.NET MVC application. I was looking for how to get my SMTP requests to be sent over TLS1.2 and NOT over TLS1.0. I also added &= ~SecurityProtocolType.Tls to turn off TLS 1.0
In VB the equivalent is Net.ServicePointManager.SecurityProtocol = Net.ServicePointManager.SecurityProtocol OR Net.SecurityProtocolType.Tls12 OR Net.SecurityProtocolType.Tls12
L
Luke Hutton

The default System.Net.ServicePointManager.SecurityProtocol in both .NET 4.0/4.5 is SecurityProtocolType.Tls|SecurityProtocolType.Ssl3.

.NET 4.0 supports up to TLS 1.0 while .NET 4.5 supports up to TLS 1.2

However, an application targeting .NET 4.0 can still support up to TLS 1.2 if .NET 4.5 is installed in the same environment. .NET 4.5 installs on top of .NET 4.0, replacing System.dll.

I've verified this by observing the correct security protocol set in traffic with fiddler4 and by manually setting the enumerated values in a .NET 4.0 project:

ServicePointManager.SecurityProtocol = (SecurityProtocolType)192 |
(SecurityProtocolType)768 | (SecurityProtocolType)3072;

Reference:

namespace System.Net
{
    [System.Flags]
    public enum SecurityProtocolType
    {
       Ssl3 = 48,
       Tls = 192,
       Tls11 = 768,
       Tls12 = 3072,
    }
}

If you attempt the hack on an environment with ONLY .NET 4.0 installed, you will get the exception:

Unhandled Exception: System.NotSupportedException: The requested security protocol is not supported. at System.Net.ServicePointManager.set_SecurityProtocol(SecurityProtocolType v alue)

However, I wouldn't recommend this "hack" since a future patch, etc. may break it.*

Therefore, I've decided the best route to remove support for SSLv3 is to:

Upgrade all applications to .NET 4.5 Add the following to boostrapping code to override the default and future proof it: System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;

*Someone correct me if this hack is wrong, but initial tests I see it works


Please see imperialviolet.org/2014/12/08/poodleagain.html "This seems like a good moment to reiterate that everything less than TLS 1.2 with an AEAD cipher suite is cryptographically broken."
@Mathew, by viewing the source code of ServicePointManager.cs see referencesource.microsoft.com/#System/net/System/Net/…
I keep seeing people claim the .NET 4.5 defaults to Tls12 - but as you've put here, it does not. It gives you the option to use it for SecurityProtocol
I won't downvote this answer since it does provide a lot of helpful information, but implementing a hardcoded protocol version is not a good idea as it will restrict the application from using best available encryption and may result in security issues down the road. The registry changes to change the default behavior of .Net to actually support modern protocols is very much preferable. (It is, however, worth noting the registry change also disables SSL v3.)
On FW 4.6 and 4.7, the default is now SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12 as per support.microsoft.com/en-us/help/3069494/…
F
Franklin Yu

You can override the default behavior in following registry:

Key  : HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319 
Value: SchUseStrongCrypto
Type: REG_DWORD
Data : 1

and

Key  : HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\.NETFramework\v4.0.30319
Value: SchUseStrongCrypto
Type: REG_DWORD
Data : 1

For details, please see the implementation of ServicePointManager.


Thanks, I didn't know about this. I will test it. I created a powershel script to set it: gist.github.com/lukehutton/ab80d207172a923401b1
Changing registry does not look like a good solution. If application wants to support TLS1 then the application should take cate about it. Not the running environment. Otherwise it could harm other applications or make a hell from deploying and upgrading your application.
@MikhailG quite the opposite. The registry change is the preferable method. SChannel provides an abstraction of the underlying negotiation and you want your application to use whatever the highest supported security level is. Artificially limiting it in software results in future problems when new protocols are released and your software is unable to use them. It would be nice if there was an option to say use only better than a given protocol in software, but there is no option for that without also preventing future versions from working. The did disable SSL v3 with that change though..
Command-line: reg add HKLM\SOFTWARE\Microsoft\.NETFramework\v4.0.30319 /v SchUseStrongCrypto /t REG_DWORD /d 1 /reg:64 (and/or /reg:32)
@MikhailG: Setting the registry does not prevent applications from supporting older protocols. It only changes the defaults (which include tls 1.0 as of now). Further, the default behavior in .Net 4.6+ is to use strong crypto; in that case this registry entry would only be useful as a means to disable strong crypto.
d
dana

Create a text file with a .reg extension and the following contents:

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

Or download it from the following source:

https://gist.githubusercontent.com/dana-n/174759ce95e04fa1a8fd691f633ccbd3/raw/NET40-Enable-TLS-1_2.reg

Double-click to install...


The link you provided seems to have SSL certificate issues.
Even when I add these registry key, I still have that issue. Any idea ?
@Samidjo - What .NET version are you using? Luke's answer goes into a lot more detail than mine, but it looks like you need to at least have .NET 4.5 installed. Also, if you just made the change, you may have to recycle the app pool. These are kind of guesses, so without more detail I might be able to help much further :)
A recently applied patch support.microsoft.com/en-us/help/4019114/… to a server caused our .net 4.5.2 application to fail on https REST requests. These keys solved our problem.
J
Jim

I have found that when I specify only TLS 1.2 that it will still down negotiate to 1.1. System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

I have specified this in the Global.asax startup method for my .net 4.5 web app.


What is the supported security protocol on the server? I believe that is factor here too and may be 1.1 is the latest on the server. www.passionatecoder.ca
Upvoted because this is the only answer that states WHERE to put the line of code that is the solution.
Client (e.g. your C# WebClient) and the Server (API server you're calling) will negotiate to use the highest protocol that both support. So if your client supports TLS 1.2, but the server only TLS 1.1 - the Client will use TLS 1.1 (unless you REMOVE TLS 1.1 from your client - in which case they may not find a mutually supported protocol, and Client will error)
Had to add using System.Net in global.asax.cs
M
Marcel

Following code will:

print enabled protocols

print available protocols

enable TLS1.2 if platform supports it and if it is not enabled to begin with

disable SSL3 if it is enabled

print end result

Constants:

48 is SSL3

192 is TLS1

768 is TLS1.1

3072 is TLS1.2

Other protocols will not be affected. This makes this compatible with future protocols (Tls1.3, etc).

Code

// print initial status
    Console.WriteLine("Runtime: " + System.Diagnostics.FileVersionInfo.GetVersionInfo(typeof(int).Assembly.Location).ProductVersion);
    Console.WriteLine("Enabled protocols:   " + ServicePointManager.SecurityProtocol);
    Console.WriteLine("Available protocols: ");
    Boolean platformSupportsTls12 = false;
    foreach (SecurityProtocolType protocol in Enum.GetValues(typeof(SecurityProtocolType))) {                
        Console.WriteLine(protocol.GetHashCode());
        if (protocol.GetHashCode() == 3072){
            platformSupportsTls12 = true;
        }
    }
    Console.WriteLine("Is Tls12 enabled: " + ServicePointManager.SecurityProtocol.HasFlag((SecurityProtocolType)3072));    


// enable Tls12, if possible
    if (!ServicePointManager.SecurityProtocol.HasFlag((SecurityProtocolType)3072)){
        if (platformSupportsTls12){
            Console.WriteLine("Platform supports Tls12, but it is not enabled. Enabling it now.");
            ServicePointManager.SecurityProtocol |= (SecurityProtocolType)3072;
        } else {
            Console.WriteLine("Platform does not supports Tls12.");
        }
    }

// disable ssl3
   if (ServicePointManager.SecurityProtocol.HasFlag(SecurityProtocolType.Ssl3)) { 
      Console.WriteLine("Ssl3SSL3 is enabled. Disabling it now.");
      // disable SSL3. Has no negative impact if SSL3 is already disabled. The enclosing "if" if just for illustration.
      System.Net.ServicePointManager.SecurityProtocol &= ~SecurityProtocolType.Ssl3;                      
   }
    Console.WriteLine("Enabled protocols:   " + ServicePointManager.SecurityProtocol);

Output

Runtime: 4.7.2114.0
Enabled protocols:   Ssl3, Tls
Available protocols: 
0
48
192
768
3072
Is Tls12 enabled: False
Platform supports Tls12, but it is not enabled. Enabling it now.
Ssl3 is enabled. Disabling it now.
Enabled protocols:   Tls, Tls12

H
Hieu

I got the problem when my customer upgraded TLS from 1.0 to 1.2. My application is using .net framework 3.5 and run on server. So i fixed it by this way:

Fix the program

Before call HttpWebRequest.GetResponse() add this command:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolTypeExtensions.Tls11 | SecurityProtocolTypeExtensions.Tls12;

Extensions 2 DLLs by adding 2 new classes: System.Net and System.Security.Authentication

    namespace System.Net
    {
        using System.Security.Authentication;
        public static class SecurityProtocolTypeExtensions
        {
            public const SecurityProtocolType Tls12 = (SecurityProtocolType)SslProtocolsExtensions.Tls12;
            public const SecurityProtocolType Tls11 = (SecurityProtocolType)SslProtocolsExtensions.Tls11;
            public const SecurityProtocolType SystemDefault = (SecurityProtocolType)0;
        }
    } 

    namespace System.Security.Authentication
    {
        public static class SslProtocolsExtensions
        {
            public const SslProtocols Tls12 = (SslProtocols)0x00000C00;
            public const SslProtocols Tls11 = (SslProtocols)0x00000300;
        }
    } 

Update Microsoft batch

Download batch:

For windows 2008 R2: windows6.1-kb3154518-x64.msu

For windows 2012 R2: windows8.1-kb3154520-x64.msu

For download batch and more details you can see here:

https://support.microsoft.com/en-us/help/3154518/support-for-tls-system-default-versions-included-in-the-.net-framework-3.5.1-on-windows-7-sp1-and-server-2008-r2-sp1


is it possible the change SecurityProtocol without changing source code ? like a machine.config or app.config.
Wow. That's voodoo of the year award..stuff...right there. You rock the suburbs!
U
Uwe Keim

The registry change mechanism worked for me after a struggle. Actually my application was running as 32bit. So I had to change the value under path.

HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft.NETFramework\v4.0.30319

https://i.stack.imgur.com/NGeTH.png


It's not accurate. For .NET 4.5.2, this needs to be set to 1 (or above); but for .NET 4.6, it suffices not to be set to 0 (that is, it can be unset).
Oh I didnt test in .Net 4.6. My findings are there in blogpost joymonscode.blogspot.com/2015/08/…
The registry key you mention should read "Wow6432Node". You omitted the "Node" part for some reason. I tried to edit your response but my change was only 4 letters so it wouldn't let me. :\
I had to bounce IIS to have this setting active itself as the default.
R
Roger Sanders

I'm running under .NET 4.5.2, and I wasn't happy with any of these answers. As I'm talking to a system which supports TLS 1.2, and seeing as SSL3, TLS 1.0, and TLS 1.1 are all broken and unsafe for use, I don't want to enable these protocols. Under .NET 4.5.2, the SSL3 and TLS 1.0 protocols are both enabled by default, which I can see in code by inspecting ServicePointManager.SecurityProtocol. Under .NET 4.7, there's the new SystemDefault protocol mode which explicitly hands over selection of the protocol to the OS, where I believe relying on registry or other system configuration settings would be appropriate. That doesn't seem to be supported under .NET 4.5.2 however. In the interests of writing forwards-compatible code, that will keep making the right decisions even when TLS 1.2 is inevitably broken in the future, or when I upgrade to .NET 4.7+ and hand over more responsibility for selecting an appropriate protocol to the OS, I adopted the following code:

SecurityProtocolType securityProtocols = ServicePointManager.SecurityProtocol;
if (securityProtocols.HasFlag(SecurityProtocolType.Ssl3) || securityProtocols.HasFlag(SecurityProtocolType.Tls) || securityProtocols.HasFlag(SecurityProtocolType.Tls11))
{
    securityProtocols &= ~(SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11);
    if (securityProtocols == 0)
    {
        securityProtocols |= SecurityProtocolType.Tls12;
    }
    ServicePointManager.SecurityProtocol = securityProtocols;
}

This code will detect when a known insecure protocol is enabled, and in this case, we'll remove these insecure protocols. If no other explicit protocols remain, we'll then force enable TLS 1.2, as the only known secure protocol supported by .NET at this point in time. This code is forwards compatible, as it will take into consideration new protocol types it doesn't know about being added in the future, and it will also play nice with the new SystemDefault state in .NET 4.7, meaning I won't have to re-visit this code in the future. I'd strongly recommend adopting an approach like this, rather than hard-coding any particular security protocol states unconditionally, otherwise you'll have to recompile and replace your client with a new version in order to upgrade to a new security protocol when TLS 1.2 is inevitably broken, or more likely you'll have to leave the existing insecure protocols turned on for years on your server, making your organisation a target for attacks.


This answer seems like the most thought out, however, unless I'm missing something, I'm not sure it will be forward compatible whenever TLS 1.2 inevitably breaks. From what I'm seeing in my .NET 4.7.2 app, the SecurityProtocolType.SystemDefault flag evaluates to 0, so checking if (securityProtocols == 0) with the bitwise inclusive or flag for TLS 1.2 will always include TLS 1.2, even after it is "breaks", right? Not sharp shooting here. I am genuinely trying to find the best path forward.
I've modified your code to include this and it appears to work and be forward compatible: if (!Enum.IsDefined(typeof(SecurityProtocolType), 0) && securityProtocols == 0) { securityProtocols |= SecurityProtocolType.Tls12; }.
@Griswald_911, I haves similar code in my 4.7.2 console application, and I found this line securityProtocols |= SecurityProtocolType.Tls12; (without if block) does not maintain SystemDefault, the securityProtocols only has TLS2 afterward. So do you mean when value is SystemDefault, no value should be updated? Regarding the forward compatible, are you assuming the OS would take care of enabling newer protocol like TLS 1.3?
@Yang -- Correct. The line securityProtocols |= SecurityProtocolType.Tls12;' will add TLS 1.2, but because the SecurityProtocolType` enum has a [Flags] attribute, and the SystemDefault enumeration value is 0, the SystemDefault value will be stripped, even if it was previously set. The end result is that you can either set the SevicePointManager.SecurityProtocol to 0, or to any combination of the other enumeration values. If you set it to SystemDefault, you are basically opting out of specifying the protocol yourself and letting the OS decide.
@Yang -- The point is that, after setting the value to SystemDefault, your app should use whatever the OS specifies--which is TLS 1.2 in the latest versions of Windows 10.The idea is that, in the future when TLS 1.3 becomes the standard, you shouldn't have to modify your application to inherit that functionality. See the documentation here, where SystemDefault "allows the operating system to choose the best protocol to use, and to block protocols that are not secure".
J
JohnLBevan

Microsoft recently published best practices around this. https://docs.microsoft.com/en-us/dotnet/framework/network-programming/tls

Summary

Target .Net Framework 4.7, remove any code setting the SecurityProtocol, thus the OS will ensure you use the most secure solution.

NB: You will also need to ensure that the latest version of TLS is supported & enabled on your OS.

OS                          TLS 1.2 support

Windows 10                  \_ Supported, and enabled by default.
Windows Server 2016         /   
Windows 8.1                 \_ Supported, and enabled by default.
Windows Server 2012 R2      /
Windows 8.0                 \_ Supported, and enabled by default.
Windows Server 2012         /
Windows 7 SP1               \_ Supported, but not enabled by default*.
Windows Server 2008 R2 SP1  /
Windows Server 2008         -  Support for TLS 1.2 and TLS 1.1 requires an update. See Update to add support for TLS 1.1 and TLS 1.2 in Windows Server 2008 SP2.
Windows Vista               -  Not supported.

* To enable TLS1.2 via the registry see https://docs.microsoft.com/en-us/windows-server/security/tls/tls-registry-settings#tls-12 

    Path: HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server

        Property: Enabled
        Type: REG_DWORD
        Value: 1

        Property: DisabledByDefault 
        Type: REG_DWORD
        Value: 0

    Path: HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client

        Property: Enabled
        Type: REG_DWORD
        Value: 1

        Property: DisabledByDefault 
        Type: REG_DWORD
        Value: 0

For more information and older frameworks, please refer to the MS link.


Problem is that tls 1.1 and tls 1.2 won't work on Windows 7 and Server 2008 if you follow the guidelines (keeping SecurityProtocolType.SystemDefault) because they are not "enabled" (whatever that means) in these os' without a registry change. This makes SystemDefault in practice broken by design. Microsoft really messed up this one.
Nice one, thanks @osexpert, good catch. I've amended the answer to include info on supported OSes, so there are no surprises for people running older OSes where just targeting 4.7 isn't enough.
NB: There's also a KB to enable the newer protocols on some OSes: support.microsoft.com/en-my/help/3140245/…
If registry settings are not an option I think this is the best solution for .NET 4.7+: if (System.Environment.OSVersion.Version < new Version(6, 2) /* Windows 8 */) ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; else ServicePointManager.SecurityProtocol = SecurityProtocolType.SystemDefault;
q
qbik

For completeness, here is a Powershell script that sets aforementioned registry keys:

new-itemproperty -path "HKLM:\SOFTWARE\Microsoft\.NETFramework\v4.0.30319" -name "SchUseStrongCrypto" -Value 1 -PropertyType "DWord";
new-itemproperty -path "HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v4.0.30319" -name "SchUseStrongCrypto" -Value 1 -PropertyType "DWord"

S
Sagar Borole

There are two possible scenario,

If you application run on .net framework 4.5 or less than that and you can easily deploy new code to the production then you can use of below solution. You can add below line of code before making api call, ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; // .NET 4.5 If you cannot deploy new code and you want to resolve with the same code which is present in the production, then you have two options.

Option 1 :

[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


then create a file with extension .reg and install.

Note : This setting will apply at registry level and is applicable to all application present on that machine and if you want to restrict to only single application then you can use Option 2

Option 2 : This can be done by changing some configuration setting in config file. You can add either of one in your config file.

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

or

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

V
Vikrant

An alternative to hard-coding ServicePointManager.SecurityProtocol or the explicit SchUseStrongCrypto key as mentioned above:
You can tell .NET to use the default SCHANNEL settings with the SystemDefaultTlsVersions key,
e.g.:

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319] "SystemDefaultTlsVersions"=dword:00000001
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v4.0.30319] "SystemDefaultTlsVersions"=dword:00000001

G
G W C

The BEST solution to this problem appears to be to upgrade to at least .NET 4.6 or later, which will automatically choose strong protocols as well as strong ciphers.

If you can't upgrade to .NET 4.6, the advice of setting

System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;

And using the registry settings:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft.NETFramework\v4.0.30319 – SchUseStrongCrypto = DWORD of 1 HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft.NETFramework\v4.0.30319 – SchUseStrongCrypto = DWORD of 1

Results in using something other than TLS 1.0 and a strong cipher.

In my testing, only the setting in the Wow6432Node made any difference, even though my test application was built for Any CPU.


Clarification: you need only set the SevicePointManager.SecurityProtocol OR set the registry settings. There's no need to do both. For my application, I opted to just set ServicePointManager.SecurityProtocol. My reasoning is that setting the registry affects the entire machine, and I didn't want someone else's application breaking because it depended on TLS 1.0.
B
Benjamin Freitag

According to Transport Layer Security (TLS) best practices with the .NET Framework: To ensure .NET Framework applications remain secure, the TLS version should not be hardcoded. Instead set the registry keys: SystemDefaultTlsVersions and SchUseStrongCrypto:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\.NETFramework\v2.0.50727]
"SystemDefaultTlsVersions"=dword:00000001
"SchUseStrongCrypto"=dword:00000001

[HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\.NETFramework\v4.0.30319]
"SystemDefaultTlsVersions"=dword:00000001
"SchUseStrongCrypto"=dword:00000001

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v2.0.50727]
"SystemDefaultTlsVersions"=dword:00000001
"SchUseStrongCrypto"=dword:00000001

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319]
"SystemDefaultTlsVersions"=dword:00000001
"SchUseStrongCrypto"=dword:00000001

y
yanivhs

If you can use .NET 4.7.1 or newer, it will use TLS 1.2 as the minimum protocol based on the operating system capabilities. Per Microsoft recommendation :

To ensure .NET Framework applications remain secure, the TLS version should not be hardcoded. .NET Framework applications should use the TLS version the operating system (OS) supports.

k
kgw

For Key: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft.NETFramework\v4.0.30319 Value: SchUseStrongCrypto

You have to set the value to 1.


I think you're getting downvoted because its the same answer @Jira Mares offered, but with less detail