77

I have a Windows server 2008 R2 server running a dozen .NET Framework 4.0 WebForms applications, and I need to disable TLS 1.0 and lower. When I do that, all secure connections fail and I was forced to re-enable TLS 1.0. Is there any way to use TLS 1.2 in a framework 4.0 environment? Perhaps I am missing something?

Also, due to limitations of the version CMS we are using, we cannot upgrade the Framework at this time.

betagreg
  • 881
  • 1
  • 7
  • 8

7 Answers7

90

If you are not able to add a property to system.net class library.

Then, add in Global.asax file:

ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072; //TLS 1.2
ServicePointManager.SecurityProtocol = (SecurityProtocolType)768; //TLS 1.1

And you can use it in a function, at the starting line:

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

And, it's being useful for STRIPE payment gateway, which only supports TLS 1.1, TLS 1.2.

EDIT: After so many questions on .NET 4.5 is installed on my server or not... here is the screenshot of Registry on my production server:

I have only .NET framework 4.0 installed.

registry

Vikrant
  • 4,922
  • 16
  • 46
  • 68
  • Would this code work for Web Service SOAP requests (ie having added a web reference). – NickG Mar 21 '17 at 18:26
  • @NickG, [This can be done](https://community.smartbear.com/t5/SoapUI-Open-Source/How-to-enable-TLS-1-2-in-SoapUI/m-p/99781/highlight/true#M17650) for SOAP. – Vikrant Mar 22 '17 at 05:33
  • 5
    I think this requires .net 4.5 to be installed, so technically this isn't a fix for .net 4.0. – NickG Mar 22 '17 at 11:42
  • I have .Net 4.0 on my server pre-implemented, this worked. – Vikrant Mar 22 '17 at 11:52
  • And you don't have 4.5 installed? – NickG Mar 22 '17 at 14:40
  • 2
    It requires .NET 4.5 installed for compilation, but you don't have to target it in the project. – Martin Apr 11 '17 at 16:01
  • 3
    Future confirmation for anyone: this works on VB .NET 3.5. `ServicePointManager.SecurityProtocol = DirectCast(3072, SecurityProtocolType) 'TLS 1.2` – petrosmm May 12 '17 at 16:01
  • 1
    @Martin but you DO need .NET 4.5 installed on the target computer for this to work. – NickG May 24 '17 at 08:34
  • Do you place it in `Application_Start` ? – zed Mar 02 '18 at 00:28
  • Sorry @zed, not exactly inside `Application_start` but at the start of Global.asax.cs, we **define it as Global variables**. so one can use those variables in project. – Vikrant Mar 06 '18 at 13:10
  • 1
    There's a typo in the first occurrence of numeric value of TLS1.1. It reads 786, but **should be 768**. Using 786 leads to an exception. Tried to edit the respone, but don't have enough reputation yet to edit less than 6 characters – kibitzerCZ Mar 12 '18 at 13:37
  • 1
    The first two lines in this post are kind of pointless. You are assigning one value to `ServicePointManager.SecurityProtocol` and then immediately overwriting it. And then you are overwriting _that_ value later on. Better off using `ServicePointManager.SecurityProtocol = ServicePointManager.SecurityProtocol | (SecurityProtocolType)768 | (SecurityProtocolType)3072` in your startup code. – JLRishe Jul 12 '18 at 19:31
  • 1
    @JLRishe : I meant, you can add any ONE of the lines in `Global.asax.cs` file. – Vikrant Jul 20 '18 at 05:34
  • 4
    The screenshot attached doesn't prove that there is no 4.5+ framework installed. They are shown under v4/Full key with a "Release" keyword: https://docs.microsoft.com/en-us/dotnet/framework/migration-guide/how-to-determine-which-versions-are-installed – pushist1y Sep 05 '18 at 09:36
  • 1
    I have to help clarify this, even casting like this does NOT work unless you have .net framework 4.5+ installed on your machine. Please don't waste your time! – jamheadart Nov 21 '19 at 06:16
72

Make the following changes in your Registry and it should work:

1.) .NET Framework strong cryptography registry keys

[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

2.) Secure Channel (Schannel) TLS 1.2 registry keys

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

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

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server]
"DisabledByDefault"=dword:00000000
"Enabled"=dword:00000001
Philipp Maurer
  • 2,428
  • 6
  • 16
  • 25
Aditya Landge
  • 955
  • 9
  • 13
  • 6
    This worked perfectly and did not require me to add the line of code the other posts are talking about. – Baxter Aug 01 '17 at 21:22
  • 5
    Fantastic, this managed to get .Net40 to talk to TLS 1.2 Payment gateways and Mail servers. Restart of the WWW Publishing service was sufficient to make it work. – ExternalUse Aug 22 '17 at 11:30
  • 4
    I needed all of these keys/values, and also needed to restart the server, but after that TLS 1.2 was supported in a .Net 4.0 application without any code changes. – cori Oct 12 '17 at 14:11
  • 3
    I wish it didn't take me 5 hours to find this post. This solved my SSL handshake error (The request was aborted: Could not create SSL/TLS secure channel). – birken25 Dec 06 '17 at 23:08
  • This failed utterly for my team. – Matt Feb 06 '18 at 19:41
  • 1
    In order for this to work, you'll also need .NET 4.6 or higher installed. More info here: https://github.com/TheLevelUp/pos-tls-patcher – user24601 Mar 08 '18 at 03:08
  • Adiyta, yep, it will work with .NET 4.0 apps that are targetted for .NET 4.0, but .NET 4.5 or higher will need to be installed to use TLS 1.2 with these registries settings. More info here: https://docs.microsoft.com/en-us/dotnet/framework/network-programming/tls – user24601 Mar 16 '18 at 01:48
  • 3
    thanks you!!! this solved my problem using github's markdown rendering services via MarkdownPad. – rev Mar 29 '18 at 01:28
  • 2
    Worked for me windows server 2012 r2 .net 4.0, restart iis, no reboot – kpg Jun 07 '18 at 14:17
  • correction - .net 4.6.1 is installed but the targeted framework is 4.0 – kpg Jun 07 '18 at 15:18
  • Do you have to restart IIS or just recycle app pool? – BVernon Sep 11 '18 at 00:13
  • Yes, this fixed DBMail (SQL Server Database Email) for us, or rather allowed it to work with (only) TLS 1.2. Astonishing that we still had to do this with SQL Server 2017 CU13 (latest release) on a fresh install of Windows Server 2016 standard (again, fully updated). – Zeek2 Mar 25 '19 at 14:49
  • 1
    Thank you! Had a .net Core project that this worked on. One day debugging started giving an SSL error in the browser and this finally fixed it. – E Benzle Jul 29 '20 at 03:24
  • Can anyone help with this.. do the reg changes have to happen on all clients that have installed my app or just on the computer creating the upload?? – Glenn Angel Nov 12 '20 at 01:28
41

The only way I have found to change this is directly on the code :

at the very beginning of your app you set

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

you should include the system.net class

I did this before calling a web service because we had to block tls1 too.

Vikrant
  • 4,922
  • 16
  • 46
  • 68
Mike
  • 731
  • 8
  • 15
  • I wasn't able to get this tested in our environment, as we may have found a way to avoid the TLS 1.0 block requirement for now, but it is the most reasonable solution I have come across. Thanks! – betagreg Dec 04 '15 at 16:25
  • 31
    This doesn't work for projects targeting .NET 4.0 because `SecurityProtocolType` has no member `Tls12`. – Martin Apr 11 '17 at 16:00
  • 60
    `ServicePointManager.SecurityProtocol = (SecurityProtocolType) 3072;` That will work in 4.0, although it might require your runtime to be fully patched/updated. – STW Apr 19 '17 at 19:04
  • 8
    While this is a year old, the answer, in my eyes, is wrong! It should be updated with the answer provided by @STW – RoLYroLLs Jul 27 '17 at 20:23
  • 13
    The accepted answer is incorrect if you are using .NET 4.0 – Krishnan Venkiteswaran Feb 28 '18 at 06:28
  • 4
    Do not hardcode the security protocol. See [TLS Best Practices with .NET](https://docs.microsoft.com/en-us/dotnet/framework/network-programming/tls) – user24601 Mar 16 '18 at 01:44
  • 4
    The question is about .NET 4.0 and this code will not compile in .NET 4.0. – JLRishe Jul 12 '18 at 19:33
  • Downvote reason: answer is wrong and doesn't work (for the reason Martin stated) – NickG Jan 04 '19 at 10:59
  • 1
    @user24601 What choice do you have if you can't upgrade to .NET 4.5 and have to use TLS 1.2? STW, I am surprised you can set an enum to an undeclared value...wouldn't have expected that to compile or run. Thanks – xr280xr Jan 06 '19 at 22:40
  • 1
    If you don’t have .NET 4.5 you can try forcing TLS version 1.2 using the integer value for the enum. See comment by STW. This will compile but may result in a runtime error if TLS 1.2 is not available to the OS. – user24601 Jan 06 '19 at 23:10
  • 1
    @xr280xr, keep in mind if you can install .NET 4.5 runtime on the target, you do not need to rebuild your app to target .NET 4.5 as long as you're targetting 4.0 and you set the appropriate registry settings. See here for more details: https://github.com/TheLevelUp/pos-tls-patcher – user24601 Jan 06 '19 at 23:19
  • I wouldn't go with hard coding. – M. Fawad Surosh Jan 15 '19 at 22:07
  • Hard-coding can't be avoided if you can't upgrade your development environment to .NET 4.5 or later that includes the new [`SecurityProtocolType`](https://docs.microsoft.com/en-us/dotnet/api/system.net.securityprotocoltype). This compiles and works under .NET 4.0, as long as .NET 4.5 or later is installed on the target machine. Best practice may be to upgrade, but this is a _practical_ solution. – Suncat2000 Mar 09 '21 at 17:33
27

According to this, you will need .NET 4.5 installed. For more details, visit the webpage. The gist of it is that after you have .NET 4.5 installed, your 4.0 apps will use the 4.5 System.dll. You can enable TLS 1.2 in two ways:

  • At the beginning of the application, add this code: ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;
  • Set the registry key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319: SchUseStrongCrypto to DWORD 1
Vikrant
  • 4,922
  • 16
  • 46
  • 68
BrainStorm.exe
  • 1,287
  • 3
  • 21
  • 37
  • 4
    In order to get TLS 1.2 without code changes, you'll also need .NET 4.6 installed in addition to the registry keys. More info here: https://github.com/TheLevelUp/pos-tls-patcher – user24601 Mar 08 '18 at 03:10
13

I code in VB and was able to add the following line to my Global.asax.vb file inside of Application_Start

ServicePointManager.SecurityProtocol = CType(3072, SecurityProtocolType)    'TLS 1.2
user2721607
  • 269
  • 3
  • 5
4

There are two possible scenarios,

  1. If your application runs on .net framework 4.5 or less, and you can easily deploy new code to the production then you can use of below solution.

    You can add the below line of code before making the API call,

    ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; // .NET 4.5
    ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072; // .NET 4.0
    
  2. If you cannot deploy new code and you want to resolve the issue 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 in your config file.

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

or

<runtime>
  <AppContextSwitchOverrides value="Switch.System.Net.DontEnableSystemDefaultTlsVersions=false"
</runtime>
incarnadine
  • 654
  • 4
  • 16
sagar borole
  • 101
  • 4
0

I meet the same issue on a Windows installed .NET Framework 4.0.
And I Solved this issue by installing .NET Framework 4.6.2.
Or you may download the newest package to have a try.

Krain Chen
  • 11
  • 1