We are unable to connect to an HTTPS server using WebRequest because of this error message:
The request was aborted: Could not create SSL/TLS secure channel.
We know that the server doesn't have a valid HTTPS certificate with the path used, but to bypass this issue, we use the following code that we've taken from another StackOverflow post:
private void Somewhere() {
ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(AlwaysGoodCertificate);
}
private static bool AlwaysGoodCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors policyErrors) {
return true;
}
The problem is that server never validates the certificate and fails with the above error. Does anyone have any idea of what I should do?
I should mention that a colleague and I performed tests a few weeks ago and it was working fine with something similar to what I wrote above. The only "major difference" we've found is that I'm using Windows 7 and he was using Windows XP. Does that change something?
I finally found the answer (I haven't noted my source but it was from a search);
While the code works in Windows XP, in Windows 7, you must add this at the beginning:
// using System.Net;
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
// Use SecurityProtocolType.Ssl3 if needed for compatibility reasons
And now, it works perfectly.
ADDENDUM
As mentioned by Robin French; if you are getting this problem while configuring PayPal, please note that they won't support SSL3 starting by December, 3rd 2018. You'll need to use TLS. Here's Paypal page about it.
The solution to this, in .NET 4.5 is
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
If you don’t have .NET 4.5 then use
ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;
Make sure the ServicePointManager settings are made before the HttpWebRequest is created, else it will not work.
Works:
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls
| SecurityProtocolType.Tls11
| SecurityProtocolType.Tls12
| SecurityProtocolType.Ssl3;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://google.com/api/")
Fails:
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://google.com/api/")
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls
| SecurityProtocolType.Tls11
| SecurityProtocolType.Tls12
| SecurityProtocolType.Ssl3;
Note: Several of the highest voted answers here advise setting ServicePointManager.SecurityProtocol, but Microsoft explicitly advises against doing that. Below, I go into the typical cause of this issue and the best practices for resolving it.
One of the biggest causes of this issue is the active .NET Framework version. The .NET framework runtime version affects which security protocols are enabled by default.
In ASP.NET sites, the framework runtime version is often specified in web.config. (see below)
In other apps, the runtime version is usually the version for which the project was built, regardless of whether it is running on a machine with a newer .NET version.
There doesn't seem to be any authoritative documentation on how it specifically works in different versions, but it seems the defaults are determined more or less as follows:
Framework Version
Default Protocols
4.5 and earlier
SSL 3.0, TLS 1.0
4.6.x
TLS 1.0, 1.1, 1.2, 1.3
4.7+
System (OS) Defaults
For the older versions, your mileage may vary somewhat based on which .NET runtimes are installed on the system. For example, there could be a situation where you are using a very old framework and TLS 1.0 is not supported, or using 4.6.x and TLS 1.3 is not supported.
Microsoft's documentation strongly advises using 4.7+ and the system defaults:
We recommend that you:
Target .NET Framework 4.7 or later versions on your apps. Target .NET Framework 4.7.1 or later versions on your WCF apps.
Do not specify the TLS version. Configure your code to let the OS decide on the TLS version.
Perform a thorough code audit to verify you're not specifying a TLS or SSL version.
For ASP.NET sites: check the targetFramework version in your <httpRuntime> element, as this (when present) determines which runtime is actually used by your site:
<httpRuntime targetFramework="4.5" />
Better:
<httpRuntime targetFramework="4.7" />
I had this problem trying to hit https://ct.mob0.com/Styles/Fun.png, which is an image distributed by CloudFlare on its CDN that supports crazy stuff like SPDY and weird redirect SSL certs.
Instead of specifying Ssl3 as in Simons answer I was able to fix it by going down to Tls12 like this:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
new WebClient().DownloadData("https://ct.mob0.com/Styles/Fun.png");
The problem you're having is that the aspNet user doesn't have access to the certificate. You have to give access using the winhttpcertcfg.exe
An example on how to set this up is at:
http://support.microsoft.com/kb/901183
Under step 2 in more information
EDIT: In more recent versions of IIS, this feature is built in to the certificate manager tool - and can be accessed by right clicking on the certificate and using the option for managing private keys. More details here: https://serverfault.com/questions/131046/how-to-grant-iis-7-5-access-to-a-certificate-in-certificate-store/132791#132791
After many long hours with this same issue I found that the ASP.NET account the client service was running under didn't have access to the certificate. I fixed it by going into the IIS Application Pool that the web app runs under, going into Advanced Settings, and changing the Identity to the LocalSystem account from NetworkService.
A better solution is to get the certificate working with the default NetworkService account but this works for quick functional testing.
The error is generic and there are many reasons why the SSL/TLS negotiation may fail. The most common is an invalid or expired server certificate, and you took care of that by providing your own server certificate validation hook, but is not necessarily the only reason. The server may require mutual authentication, it may be configured with a suites of ciphers not supported by your client, it may have a time drift too big for the handshake to succeed and many more reasons.
The best solution is to use the SChannel troubleshooting tools set. SChannel is the SSPI provider responsible for SSL and TLS and your client will use it for the handshake. Take a look at TLS/SSL Tools and Settings.
Also see How to enable Schannel event logging.
The approach with setting
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12
Seems to be okay, because Tls1.2 is latest version of secure protocol. But I decided to look deeper and answer do we really need to hardcode it.
Specs: Windows Server 2012R2 x64.
From the internet there is told that .NetFramework 4.6+ must use Tls1.2 by default. But when I updated my project to 4.6 nothing happened.
I have found some info that tells I need manually do some changes to enable Tls1.2 by default
https://support.microsoft.com/en-in/help/3140245/update-to-enable-tls-1-1-and-tls-1-2-as-default-secure-protocols-in-wi
But proposed windows update doesnt work for R2 version
But what helped me is adding 2 values to registry. You can use next PS script so they will be added automatically
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NetFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -Value '1' -Type DWord
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\.NetFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -Value '1' -Type DWord
That is kind of what I was looking for. But still I cant answer on question why NetFramework 4.6+ doesn't set this ...Protocol value automatically?
Another possible cause of the The request was aborted: Could not create SSL/TLS secure channel error is a mismatch between your client PC's configured cipher_suites values, and the values that the server is configured as being willing and able to accept. In this case, when your client sends the list of cipher_suites values that it is able to accept in its initial SSL handshaking/negotiation "Client Hello" message, the server sees that none of the provided values are acceptable, and may return an "Alert" response instead of proceeding to the "Server Hello" step of the SSL handshake.
To investigate this possibility, you can download Microsoft Message Analyzer, and use it to run a trace on the SSL negotiation that occurs when you try and fail to establish an HTTPS connection to the server (in your C# app).
If you are able to make a successful HTTPS connection from another environment (e.g. the Windows XP machine that you mentioned -- or possibly by hitting the HTTPS URL in a non-Microsoft browser that doesn't use the OS's cipher suite settings, such as Chrome or Firefox), run another Message Analyzer trace in that environment to capture what happens when the SSL negotiation succeeds.
Hopefully, you'll see some difference between the two Client Hello messages that will allow you to pinpoint exactly what about the failing SSL negotiation is causing it to fail. Then you should be able to make configuration changes to Windows that will allow it to succeed. IISCrypto is a great tool to use for this (even for client PCs, despite the "IIS" name).
The following two Windows registry keys govern the cipher_suites values that your PC will use:
HKLM\SOFTWARE\Policies\Microsoft\Cryptography\Configuration\SSL\00010002
HKLM\SYSTEM\CurrentControlSet\Control\Cryptography\Configuration\Local\SSL\00010002
Here's a full writeup of how I investigated and solved an instance of this variety of the Could not create SSL/TLS secure channel problem: http://blog.jonschneider.com/2016/08/fix-ssl-handshaking-error-in-windows.html
Something the original answer didn't have. I added some more code to make it bullet proof.
ServicePointManager.Expect100Continue = true;
ServicePointManager.DefaultConnectionLimit = 9999;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12 | SecurityProtocolType.Ssl3;
The top-voted answer will probably be enough for most people. However, in some circumstances, you could continue getting a "Could not create SSL/TLS secure channel" error even after forcing TLS 1.2. If so, you may want to consult this helpful article for additional troubleshooting steps. To summarize: independent of the TLS/SSL version issue, the client and server must agree on a "cipher suite." During the "handshake" phase of the SSL connection, the client will list its supported cipher-suites for the server to check against its own list. But on some Windows machines, certain common cipher-suites may have been disabled (seemingly due to well-intentioned attempts to limit attack surface), decreasing the possibility of the client & server agreeing on a cipher suite. If they cannot agree, then you may see "fatal alert code 40" in the event viewer and "Could not create SSL/TLS secure channel" in your .NET program.
The aforementioned article explains how to list all of a machine's potentially-supported cipher suites and enable additional cipher suites through the Windows Registry. To help check which cipher suites are enabled on the client, try visiting this diagnostic page in MSIE. (Using System.Net tracing may give more definitive results.) To check which cipher suites are supported by the server, try this online tool (assuming that the server is Internet-accessible). It should go without saying that Registry edits must be done with caution, especially where networking is involved. (Is your machine a remote-hosted VM? If you were to break networking, would the VM be accessible at all?)
In my company's case, we enabled several additional "ECDHE_ECDSA" suites via Registry edit, to fix an immediate problem and guard against future problems. But if you cannot (or will not) edit the Registry, then numerous workarounds (not necessarily pretty) come to mind. For example: your .NET program could delegate its SSL traffic to a separate Python program (which may itself work, for the same reason that Chrome requests may succeed where MSIE requests fail on an affected machine).
This one is working for me in MVC webclient
public string DownloadSite(string RefinedLink)
{
try
{
Uri address = new Uri(RefinedLink);
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
using (WebClient webClient = new WebClient())
{
var stream = webClient.OpenRead(address);
using (StreamReader sr = new StreamReader(stream))
{
var page = sr.ReadToEnd();
return page;
}
}
}
catch (Exception e)
{
log.Error("DownloadSite - error Lin = " + RefinedLink, e);
return null;
}
}
"The request was aborted: Could not create SSL/TLS secure channel" exception can occur if the server is returning an HTTP 401 Unauthorized response to the HTTP request.
You can determine if this is happening by turning on trace-level System.Net logging for your client application, as described in this answer.
Once that logging configuration is in place, run the application and reproduce the error, then look in the logging output for a line like this:
System.Net Information: 0 : [9840] Connection#62912200 - Received status line: Version=1.1, StatusCode=401, StatusDescription=Unauthorized.
In my situation, I was failing to set a particular cookie that the server was expecting, leading to the server responding to the request with the 401 error, which in turn led to the "Could not create SSL/TLS secure channel" exception.
Another possibility is improper certificate importation on the box. Make sure to select encircled check box. Initially I didn't do it, so code was either timing out or throwing same exception as private key could not be located.
I had this problem because my web.config had:
<httpRuntime targetFramework="4.5.2" />
and not:
<httpRuntime targetFramework="4.6.1" />
Doing this helped me:
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
Finally found solution for me.
Try this adding below line before calling https url (for .Net framework 4.5):
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
As you can tell there are plenty of reasons this might happen. Thought I would add the cause I encountered ...
If you set the value of WebRequest.Timeout to 0, this is the exception that is thrown. Below is the code I had... (Except instead of a hard-coded 0 for the timeout value, I had a parameter which was inadvertently set to 0).
WebRequest webRequest = WebRequest.Create(#"https://myservice/path");
webRequest.ContentType = "text/html";
webRequest.Method = "POST";
string body = "...";
byte[] bytes = Encoding.ASCII.GetBytes(body);
webRequest.ContentLength = bytes.Length;
var os = webRequest.GetRequestStream();
os.Write(bytes, 0, bytes.Length);
os.Close();
webRequest.Timeout = 0; //setting the timeout to 0 causes the request to fail
WebResponse webResponse = webRequest.GetResponse(); //Exception thrown here ...
The root of this exception in my case was that at some point in code the following was being called:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
This is really bad. Not only is it instructing .NET to use an insecure protocol, but this impacts every new WebClient (and similar) request made afterward within your appdomain. (Note that incoming web requests are unaffected in your ASP.NET app, but new WebClient requests, such as to talk to an external web service, are).
In my case, it was not actually needed, so I could just delete the statement and all my other web requests started working fine again. Based on my reading elsewhere, I learned a few things:
This is a global setting in your appdomain, and if you have concurrent activity, you can't reliably set it to one value, do your action, and then set it back. Another action may take place during that small window and be impacted.
The correct setting is to leave it default. This allows .NET to continue to use whatever is the most secure default value as time goes on and you upgrade frameworks. Setting it to TLS12 (which is the most secure as of this writing) will work now but in 5 years may start causing mysterious problems.
If you really need to set a value, you should consider doing it in a separate specialized application or appdomain and find a way to talk between it and your main pool. Because it's a single global value, trying to manage it within a busy app pool will only lead to trouble. This answer: https://stackoverflow.com/a/26754917/7656 provides a possible solution by way of a custom proxy. (Note I have not personally implemented it.)
In my case, the service account running the application did not have permission to access the private key. Once I gave this permission, the error went away
mmc
certificates
Expand to personal
select cert
right click
All tasks
Manage private keys
Add the service account user
If you are running your code from Visual Studio, try running Visual Studio as administrator. Fixed the issue for me.
System.Net.WebException: The request was aborted: Could not create
SSL/TLS secure channel.
In our case, we where using a software vendor so we didn't have access to modify the .NET code. Apparently .NET 4 won't use TLS v 1.2 unless there is a change.
The fix for us was adding the SchUseStrongCrypto key to the registry. You can copy/paste the below code into a text file with the .reg extension and execute it. It served as our "patch" to the problem.
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v4.0.30319]
"SchUseStrongCrypto"=dword:00000001
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319]
"SchUseStrongCrypto"=dword:00000001
I have struggled with this problem all day.
When I created a new project with .NET 4.5 I finally got it to work.
But if I downgraded to 4.0 I got the same problem again, and it was irreversable for that project (even when i tried to upgrade to 4.5 again).
Strange no other error message but "The request was aborted: Could not create SSL/TLS secure channel." came up for this error
In case that the client is a windows machine, a possible reason could be that the tls or ssl protocol required by the service is not activated.
This can be set in:
Control Panel -> Network and Internet -> Internet Options -> Advanced
Scroll settings down to "Security" and choose between
Use SSL 2.0
Use SSL 3.0
Use TLS 1.0
Use TLS 1.1
Use TLS 1.2
none of this answer not working for me , the google chrome and postman work and handshake the server but ie and .net not working. in google chrome in security tab > connection show that encrypted and authenticated using ECDHE_RSA with P-256 and AES_256_GCM cipher suite to handshake with the server.
i install IIS Crypto and in cipher suites list on windows server 2012 R2 ican't find ECDHE_RSA with P-256 and AES_256_GCM cipher suite. then i update windows to the last version but the problem not solve. finally after searches i understood that windows server 2012 R2 not support GSM correctly and update my server to windows server 2016 and my problem solved.
I was having this same issue and found this answer worked properly for me. The key is 3072. This link provides the details on the '3072' fix.
ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;
XmlReader r = XmlReader.Create(url);
SyndicationFeed albums = SyndicationFeed.Load(r);
In my case two feeds required the fix:
https://www.fbi.gov/feeds/fbi-in-the-news/atom.xml
https://www.wired.com/feed/category/gear/latest/rss
None of the answers worked for me.
This is what worked:
Instead of initializing my X509Certifiacte2 like this:
var certificate = new X509Certificate2(bytes, pass);
I did it like this:
var certificate = new X509Certificate2(bytes, pass, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable);
Notice the X509KeyStorageFlags.Exportable !!
I didn't change the rest of the code (the WebRequest itself):
// I'm not even sure the first two lines are necessary:
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
request = (HttpWebRequest)WebRequest.Create(string.Format("https://{0}.sii.cl/cvc_cgi/dte/of_solicita_folios", server));
request.Method = "GET";
request.Referer = string.Format("https://hercules.sii.cl/cgi_AUT2000/autInicio.cgi?referencia=https://{0}.sii.cl/cvc_cgi/dte/of_solicita_folios", servidor);
request.UserAgent = "Mozilla/4.0";
request.ClientCertificates.Add(certificate);
request.CookieContainer = new CookieContainer();
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
// etc...
}
In fact I'm not even sure that the first two lines are necessary...
Another possibility is that the code being executed doesn't have the required permissions.
In my case, I got this error when using Visual Studio debugger to test a call to a web service. Visual Studio wasn't running as Administrator, which caused this exception.
This fixed for me, add Network Service to permissions.
Right click on the certificate > All Tasks > Manage Private Keys... > Add... > Add "Network Service".
Related
We are unable to connect to an HTTPS server using WebRequest because of this error message:
The request was aborted: Could not create SSL/TLS secure channel.
We know that the server doesn't have a valid HTTPS certificate with the path used, but to bypass this issue, we use the following code that we've taken from another StackOverflow post:
private void Somewhere() {
ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(AlwaysGoodCertificate);
}
private static bool AlwaysGoodCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors policyErrors) {
return true;
}
The problem is that server never validates the certificate and fails with the above error. Does anyone have any idea of what I should do?
I should mention that a colleague and I performed tests a few weeks ago and it was working fine with something similar to what I wrote above. The only "major difference" we've found is that I'm using Windows 7 and he was using Windows XP. Does that change something?
I finally found the answer (I haven't noted my source but it was from a search);
While the code works in Windows XP, in Windows 7, you must add this at the beginning:
// using System.Net;
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
// Use SecurityProtocolType.Ssl3 if needed for compatibility reasons
And now, it works perfectly.
ADDENDUM
As mentioned by Robin French; if you are getting this problem while configuring PayPal, please note that they won't support SSL3 starting by December, 3rd 2018. You'll need to use TLS. Here's Paypal page about it.
The solution to this, in .NET 4.5 is
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
If you don’t have .NET 4.5 then use
ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;
Make sure the ServicePointManager settings are made before the HttpWebRequest is created, else it will not work.
Works:
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls
| SecurityProtocolType.Tls11
| SecurityProtocolType.Tls12
| SecurityProtocolType.Ssl3;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://google.com/api/")
Fails:
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://google.com/api/")
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls
| SecurityProtocolType.Tls11
| SecurityProtocolType.Tls12
| SecurityProtocolType.Ssl3;
Note: Several of the highest voted answers here advise setting ServicePointManager.SecurityProtocol, but Microsoft explicitly advises against doing that. Below, I go into the typical cause of this issue and the best practices for resolving it.
One of the biggest causes of this issue is the active .NET Framework version. The .NET framework runtime version affects which security protocols are enabled by default.
In ASP.NET sites, the framework runtime version is often specified in web.config. (see below)
In other apps, the runtime version is usually the version for which the project was built, regardless of whether it is running on a machine with a newer .NET version.
There doesn't seem to be any authoritative documentation on how it specifically works in different versions, but it seems the defaults are determined more or less as follows:
Framework Version
Default Protocols
4.5 and earlier
SSL 3.0, TLS 1.0
4.6.x
TLS 1.0, 1.1, 1.2, 1.3
4.7+
System (OS) Defaults
For the older versions, your mileage may vary somewhat based on which .NET runtimes are installed on the system. For example, there could be a situation where you are using a very old framework and TLS 1.0 is not supported, or using 4.6.x and TLS 1.3 is not supported.
Microsoft's documentation strongly advises using 4.7+ and the system defaults:
We recommend that you:
Target .NET Framework 4.7 or later versions on your apps. Target .NET Framework 4.7.1 or later versions on your WCF apps.
Do not specify the TLS version. Configure your code to let the OS decide on the TLS version.
Perform a thorough code audit to verify you're not specifying a TLS or SSL version.
For ASP.NET sites: check the targetFramework version in your <httpRuntime> element, as this (when present) determines which runtime is actually used by your site:
<httpRuntime targetFramework="4.5" />
Better:
<httpRuntime targetFramework="4.7" />
I had this problem trying to hit https://ct.mob0.com/Styles/Fun.png, which is an image distributed by CloudFlare on its CDN that supports crazy stuff like SPDY and weird redirect SSL certs.
Instead of specifying Ssl3 as in Simons answer I was able to fix it by going down to Tls12 like this:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
new WebClient().DownloadData("https://ct.mob0.com/Styles/Fun.png");
The problem you're having is that the aspNet user doesn't have access to the certificate. You have to give access using the winhttpcertcfg.exe
An example on how to set this up is at:
http://support.microsoft.com/kb/901183
Under step 2 in more information
EDIT: In more recent versions of IIS, this feature is built in to the certificate manager tool - and can be accessed by right clicking on the certificate and using the option for managing private keys. More details here: https://serverfault.com/questions/131046/how-to-grant-iis-7-5-access-to-a-certificate-in-certificate-store/132791#132791
After many long hours with this same issue I found that the ASP.NET account the client service was running under didn't have access to the certificate. I fixed it by going into the IIS Application Pool that the web app runs under, going into Advanced Settings, and changing the Identity to the LocalSystem account from NetworkService.
A better solution is to get the certificate working with the default NetworkService account but this works for quick functional testing.
The error is generic and there are many reasons why the SSL/TLS negotiation may fail. The most common is an invalid or expired server certificate, and you took care of that by providing your own server certificate validation hook, but is not necessarily the only reason. The server may require mutual authentication, it may be configured with a suites of ciphers not supported by your client, it may have a time drift too big for the handshake to succeed and many more reasons.
The best solution is to use the SChannel troubleshooting tools set. SChannel is the SSPI provider responsible for SSL and TLS and your client will use it for the handshake. Take a look at TLS/SSL Tools and Settings.
Also see How to enable Schannel event logging.
The approach with setting
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12
Seems to be okay, because Tls1.2 is latest version of secure protocol. But I decided to look deeper and answer do we really need to hardcode it.
Specs: Windows Server 2012R2 x64.
From the internet there is told that .NetFramework 4.6+ must use Tls1.2 by default. But when I updated my project to 4.6 nothing happened.
I have found some info that tells I need manually do some changes to enable Tls1.2 by default
https://support.microsoft.com/en-in/help/3140245/update-to-enable-tls-1-1-and-tls-1-2-as-default-secure-protocols-in-wi
But proposed windows update doesnt work for R2 version
But what helped me is adding 2 values to registry. You can use next PS script so they will be added automatically
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NetFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -Value '1' -Type DWord
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\.NetFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -Value '1' -Type DWord
That is kind of what I was looking for. But still I cant answer on question why NetFramework 4.6+ doesn't set this ...Protocol value automatically?
Another possible cause of the The request was aborted: Could not create SSL/TLS secure channel error is a mismatch between your client PC's configured cipher_suites values, and the values that the server is configured as being willing and able to accept. In this case, when your client sends the list of cipher_suites values that it is able to accept in its initial SSL handshaking/negotiation "Client Hello" message, the server sees that none of the provided values are acceptable, and may return an "Alert" response instead of proceeding to the "Server Hello" step of the SSL handshake.
To investigate this possibility, you can download Microsoft Message Analyzer, and use it to run a trace on the SSL negotiation that occurs when you try and fail to establish an HTTPS connection to the server (in your C# app).
If you are able to make a successful HTTPS connection from another environment (e.g. the Windows XP machine that you mentioned -- or possibly by hitting the HTTPS URL in a non-Microsoft browser that doesn't use the OS's cipher suite settings, such as Chrome or Firefox), run another Message Analyzer trace in that environment to capture what happens when the SSL negotiation succeeds.
Hopefully, you'll see some difference between the two Client Hello messages that will allow you to pinpoint exactly what about the failing SSL negotiation is causing it to fail. Then you should be able to make configuration changes to Windows that will allow it to succeed. IISCrypto is a great tool to use for this (even for client PCs, despite the "IIS" name).
The following two Windows registry keys govern the cipher_suites values that your PC will use:
HKLM\SOFTWARE\Policies\Microsoft\Cryptography\Configuration\SSL\00010002
HKLM\SYSTEM\CurrentControlSet\Control\Cryptography\Configuration\Local\SSL\00010002
Here's a full writeup of how I investigated and solved an instance of this variety of the Could not create SSL/TLS secure channel problem: http://blog.jonschneider.com/2016/08/fix-ssl-handshaking-error-in-windows.html
Something the original answer didn't have. I added some more code to make it bullet proof.
ServicePointManager.Expect100Continue = true;
ServicePointManager.DefaultConnectionLimit = 9999;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12 | SecurityProtocolType.Ssl3;
The top-voted answer will probably be enough for most people. However, in some circumstances, you could continue getting a "Could not create SSL/TLS secure channel" error even after forcing TLS 1.2. If so, you may want to consult this helpful article for additional troubleshooting steps. To summarize: independent of the TLS/SSL version issue, the client and server must agree on a "cipher suite." During the "handshake" phase of the SSL connection, the client will list its supported cipher-suites for the server to check against its own list. But on some Windows machines, certain common cipher-suites may have been disabled (seemingly due to well-intentioned attempts to limit attack surface), decreasing the possibility of the client & server agreeing on a cipher suite. If they cannot agree, then you may see "fatal alert code 40" in the event viewer and "Could not create SSL/TLS secure channel" in your .NET program.
The aforementioned article explains how to list all of a machine's potentially-supported cipher suites and enable additional cipher suites through the Windows Registry. To help check which cipher suites are enabled on the client, try visiting this diagnostic page in MSIE. (Using System.Net tracing may give more definitive results.) To check which cipher suites are supported by the server, try this online tool (assuming that the server is Internet-accessible). It should go without saying that Registry edits must be done with caution, especially where networking is involved. (Is your machine a remote-hosted VM? If you were to break networking, would the VM be accessible at all?)
In my company's case, we enabled several additional "ECDHE_ECDSA" suites via Registry edit, to fix an immediate problem and guard against future problems. But if you cannot (or will not) edit the Registry, then numerous workarounds (not necessarily pretty) come to mind. For example: your .NET program could delegate its SSL traffic to a separate Python program (which may itself work, for the same reason that Chrome requests may succeed where MSIE requests fail on an affected machine).
This one is working for me in MVC webclient
public string DownloadSite(string RefinedLink)
{
try
{
Uri address = new Uri(RefinedLink);
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
using (WebClient webClient = new WebClient())
{
var stream = webClient.OpenRead(address);
using (StreamReader sr = new StreamReader(stream))
{
var page = sr.ReadToEnd();
return page;
}
}
}
catch (Exception e)
{
log.Error("DownloadSite - error Lin = " + RefinedLink, e);
return null;
}
}
"The request was aborted: Could not create SSL/TLS secure channel" exception can occur if the server is returning an HTTP 401 Unauthorized response to the HTTP request.
You can determine if this is happening by turning on trace-level System.Net logging for your client application, as described in this answer.
Once that logging configuration is in place, run the application and reproduce the error, then look in the logging output for a line like this:
System.Net Information: 0 : [9840] Connection#62912200 - Received status line: Version=1.1, StatusCode=401, StatusDescription=Unauthorized.
In my situation, I was failing to set a particular cookie that the server was expecting, leading to the server responding to the request with the 401 error, which in turn led to the "Could not create SSL/TLS secure channel" exception.
Another possibility is improper certificate importation on the box. Make sure to select encircled check box. Initially I didn't do it, so code was either timing out or throwing same exception as private key could not be located.
I had this problem because my web.config had:
<httpRuntime targetFramework="4.5.2" />
and not:
<httpRuntime targetFramework="4.6.1" />
Doing this helped me:
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
Finally found solution for me.
Try this adding below line before calling https url (for .Net framework 4.5):
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
As you can tell there are plenty of reasons this might happen. Thought I would add the cause I encountered ...
If you set the value of WebRequest.Timeout to 0, this is the exception that is thrown. Below is the code I had... (Except instead of a hard-coded 0 for the timeout value, I had a parameter which was inadvertently set to 0).
WebRequest webRequest = WebRequest.Create(#"https://myservice/path");
webRequest.ContentType = "text/html";
webRequest.Method = "POST";
string body = "...";
byte[] bytes = Encoding.ASCII.GetBytes(body);
webRequest.ContentLength = bytes.Length;
var os = webRequest.GetRequestStream();
os.Write(bytes, 0, bytes.Length);
os.Close();
webRequest.Timeout = 0; //setting the timeout to 0 causes the request to fail
WebResponse webResponse = webRequest.GetResponse(); //Exception thrown here ...
The root of this exception in my case was that at some point in code the following was being called:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
This is really bad. Not only is it instructing .NET to use an insecure protocol, but this impacts every new WebClient (and similar) request made afterward within your appdomain. (Note that incoming web requests are unaffected in your ASP.NET app, but new WebClient requests, such as to talk to an external web service, are).
In my case, it was not actually needed, so I could just delete the statement and all my other web requests started working fine again. Based on my reading elsewhere, I learned a few things:
This is a global setting in your appdomain, and if you have concurrent activity, you can't reliably set it to one value, do your action, and then set it back. Another action may take place during that small window and be impacted.
The correct setting is to leave it default. This allows .NET to continue to use whatever is the most secure default value as time goes on and you upgrade frameworks. Setting it to TLS12 (which is the most secure as of this writing) will work now but in 5 years may start causing mysterious problems.
If you really need to set a value, you should consider doing it in a separate specialized application or appdomain and find a way to talk between it and your main pool. Because it's a single global value, trying to manage it within a busy app pool will only lead to trouble. This answer: https://stackoverflow.com/a/26754917/7656 provides a possible solution by way of a custom proxy. (Note I have not personally implemented it.)
In my case, the service account running the application did not have permission to access the private key. Once I gave this permission, the error went away
mmc
certificates
Expand to personal
select cert
right click
All tasks
Manage private keys
Add the service account user
If you are running your code from Visual Studio, try running Visual Studio as administrator. Fixed the issue for me.
System.Net.WebException: The request was aborted: Could not create
SSL/TLS secure channel.
In our case, we where using a software vendor so we didn't have access to modify the .NET code. Apparently .NET 4 won't use TLS v 1.2 unless there is a change.
The fix for us was adding the SchUseStrongCrypto key to the registry. You can copy/paste the below code into a text file with the .reg extension and execute it. It served as our "patch" to the problem.
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v4.0.30319]
"SchUseStrongCrypto"=dword:00000001
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319]
"SchUseStrongCrypto"=dword:00000001
I have struggled with this problem all day.
When I created a new project with .NET 4.5 I finally got it to work.
But if I downgraded to 4.0 I got the same problem again, and it was irreversable for that project (even when i tried to upgrade to 4.5 again).
Strange no other error message but "The request was aborted: Could not create SSL/TLS secure channel." came up for this error
In case that the client is a windows machine, a possible reason could be that the tls or ssl protocol required by the service is not activated.
This can be set in:
Control Panel -> Network and Internet -> Internet Options -> Advanced
Scroll settings down to "Security" and choose between
Use SSL 2.0
Use SSL 3.0
Use TLS 1.0
Use TLS 1.1
Use TLS 1.2
none of this answer not working for me , the google chrome and postman work and handshake the server but ie and .net not working. in google chrome in security tab > connection show that encrypted and authenticated using ECDHE_RSA with P-256 and AES_256_GCM cipher suite to handshake with the server.
i install IIS Crypto and in cipher suites list on windows server 2012 R2 ican't find ECDHE_RSA with P-256 and AES_256_GCM cipher suite. then i update windows to the last version but the problem not solve. finally after searches i understood that windows server 2012 R2 not support GSM correctly and update my server to windows server 2016 and my problem solved.
I was having this same issue and found this answer worked properly for me. The key is 3072. This link provides the details on the '3072' fix.
ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;
XmlReader r = XmlReader.Create(url);
SyndicationFeed albums = SyndicationFeed.Load(r);
In my case two feeds required the fix:
https://www.fbi.gov/feeds/fbi-in-the-news/atom.xml
https://www.wired.com/feed/category/gear/latest/rss
None of the answers worked for me.
This is what worked:
Instead of initializing my X509Certifiacte2 like this:
var certificate = new X509Certificate2(bytes, pass);
I did it like this:
var certificate = new X509Certificate2(bytes, pass, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable);
Notice the X509KeyStorageFlags.Exportable !!
I didn't change the rest of the code (the WebRequest itself):
// I'm not even sure the first two lines are necessary:
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
request = (HttpWebRequest)WebRequest.Create(string.Format("https://{0}.sii.cl/cvc_cgi/dte/of_solicita_folios", server));
request.Method = "GET";
request.Referer = string.Format("https://hercules.sii.cl/cgi_AUT2000/autInicio.cgi?referencia=https://{0}.sii.cl/cvc_cgi/dte/of_solicita_folios", servidor);
request.UserAgent = "Mozilla/4.0";
request.ClientCertificates.Add(certificate);
request.CookieContainer = new CookieContainer();
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
// etc...
}
In fact I'm not even sure that the first two lines are necessary...
Another possibility is that the code being executed doesn't have the required permissions.
In my case, I got this error when using Visual Studio debugger to test a call to a web service. Visual Studio wasn't running as Administrator, which caused this exception.
This fixed for me, add Network Service to permissions.
Right click on the certificate > All Tasks > Manage Private Keys... > Add... > Add "Network Service".
We are unable to connect to an HTTPS server using WebRequest because of this error message:
The request was aborted: Could not create SSL/TLS secure channel.
We know that the server doesn't have a valid HTTPS certificate with the path used, but to bypass this issue, we use the following code that we've taken from another StackOverflow post:
private void Somewhere() {
ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(AlwaysGoodCertificate);
}
private static bool AlwaysGoodCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors policyErrors) {
return true;
}
The problem is that server never validates the certificate and fails with the above error. Does anyone have any idea of what I should do?
I should mention that a colleague and I performed tests a few weeks ago and it was working fine with something similar to what I wrote above. The only "major difference" we've found is that I'm using Windows 7 and he was using Windows XP. Does that change something?
I finally found the answer (I haven't noted my source but it was from a search);
While the code works in Windows XP, in Windows 7, you must add this at the beginning:
// using System.Net;
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
// Use SecurityProtocolType.Ssl3 if needed for compatibility reasons
And now, it works perfectly.
ADDENDUM
As mentioned by Robin French; if you are getting this problem while configuring PayPal, please note that they won't support SSL3 starting by December, 3rd 2018. You'll need to use TLS. Here's Paypal page about it.
The solution to this, in .NET 4.5 is
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
If you don’t have .NET 4.5 then use
ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;
Make sure the ServicePointManager settings are made before the HttpWebRequest is created, else it will not work.
Works:
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls
| SecurityProtocolType.Tls11
| SecurityProtocolType.Tls12
| SecurityProtocolType.Ssl3;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://google.com/api/")
Fails:
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://google.com/api/")
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls
| SecurityProtocolType.Tls11
| SecurityProtocolType.Tls12
| SecurityProtocolType.Ssl3;
Note: Several of the highest voted answers here advise setting ServicePointManager.SecurityProtocol, but Microsoft explicitly advises against doing that. Below, I go into the typical cause of this issue and the best practices for resolving it.
One of the biggest causes of this issue is the active .NET Framework version. The .NET framework runtime version affects which security protocols are enabled by default.
In ASP.NET sites, the framework runtime version is often specified in web.config. (see below)
In other apps, the runtime version is usually the version for which the project was built, regardless of whether it is running on a machine with a newer .NET version.
There doesn't seem to be any authoritative documentation on how it specifically works in different versions, but it seems the defaults are determined more or less as follows:
Framework Version
Default Protocols
4.5 and earlier
SSL 3.0, TLS 1.0
4.6.x
TLS 1.0, 1.1, 1.2, 1.3
4.7+
System (OS) Defaults
For the older versions, your mileage may vary somewhat based on which .NET runtimes are installed on the system. For example, there could be a situation where you are using a very old framework and TLS 1.0 is not supported, or using 4.6.x and TLS 1.3 is not supported.
Microsoft's documentation strongly advises using 4.7+ and the system defaults:
We recommend that you:
Target .NET Framework 4.7 or later versions on your apps. Target .NET Framework 4.7.1 or later versions on your WCF apps.
Do not specify the TLS version. Configure your code to let the OS decide on the TLS version.
Perform a thorough code audit to verify you're not specifying a TLS or SSL version.
For ASP.NET sites: check the targetFramework version in your <httpRuntime> element, as this (when present) determines which runtime is actually used by your site:
<httpRuntime targetFramework="4.5" />
Better:
<httpRuntime targetFramework="4.7" />
I had this problem trying to hit https://ct.mob0.com/Styles/Fun.png, which is an image distributed by CloudFlare on its CDN that supports crazy stuff like SPDY and weird redirect SSL certs.
Instead of specifying Ssl3 as in Simons answer I was able to fix it by going down to Tls12 like this:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
new WebClient().DownloadData("https://ct.mob0.com/Styles/Fun.png");
The problem you're having is that the aspNet user doesn't have access to the certificate. You have to give access using the winhttpcertcfg.exe
An example on how to set this up is at:
http://support.microsoft.com/kb/901183
Under step 2 in more information
EDIT: In more recent versions of IIS, this feature is built in to the certificate manager tool - and can be accessed by right clicking on the certificate and using the option for managing private keys. More details here: https://serverfault.com/questions/131046/how-to-grant-iis-7-5-access-to-a-certificate-in-certificate-store/132791#132791
After many long hours with this same issue I found that the ASP.NET account the client service was running under didn't have access to the certificate. I fixed it by going into the IIS Application Pool that the web app runs under, going into Advanced Settings, and changing the Identity to the LocalSystem account from NetworkService.
A better solution is to get the certificate working with the default NetworkService account but this works for quick functional testing.
The error is generic and there are many reasons why the SSL/TLS negotiation may fail. The most common is an invalid or expired server certificate, and you took care of that by providing your own server certificate validation hook, but is not necessarily the only reason. The server may require mutual authentication, it may be configured with a suites of ciphers not supported by your client, it may have a time drift too big for the handshake to succeed and many more reasons.
The best solution is to use the SChannel troubleshooting tools set. SChannel is the SSPI provider responsible for SSL and TLS and your client will use it for the handshake. Take a look at TLS/SSL Tools and Settings.
Also see How to enable Schannel event logging.
The approach with setting
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12
Seems to be okay, because Tls1.2 is latest version of secure protocol. But I decided to look deeper and answer do we really need to hardcode it.
Specs: Windows Server 2012R2 x64.
From the internet there is told that .NetFramework 4.6+ must use Tls1.2 by default. But when I updated my project to 4.6 nothing happened.
I have found some info that tells I need manually do some changes to enable Tls1.2 by default
https://support.microsoft.com/en-in/help/3140245/update-to-enable-tls-1-1-and-tls-1-2-as-default-secure-protocols-in-wi
But proposed windows update doesnt work for R2 version
But what helped me is adding 2 values to registry. You can use next PS script so they will be added automatically
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NetFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -Value '1' -Type DWord
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\.NetFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -Value '1' -Type DWord
That is kind of what I was looking for. But still I cant answer on question why NetFramework 4.6+ doesn't set this ...Protocol value automatically?
Another possible cause of the The request was aborted: Could not create SSL/TLS secure channel error is a mismatch between your client PC's configured cipher_suites values, and the values that the server is configured as being willing and able to accept. In this case, when your client sends the list of cipher_suites values that it is able to accept in its initial SSL handshaking/negotiation "Client Hello" message, the server sees that none of the provided values are acceptable, and may return an "Alert" response instead of proceeding to the "Server Hello" step of the SSL handshake.
To investigate this possibility, you can download Microsoft Message Analyzer, and use it to run a trace on the SSL negotiation that occurs when you try and fail to establish an HTTPS connection to the server (in your C# app).
If you are able to make a successful HTTPS connection from another environment (e.g. the Windows XP machine that you mentioned -- or possibly by hitting the HTTPS URL in a non-Microsoft browser that doesn't use the OS's cipher suite settings, such as Chrome or Firefox), run another Message Analyzer trace in that environment to capture what happens when the SSL negotiation succeeds.
Hopefully, you'll see some difference between the two Client Hello messages that will allow you to pinpoint exactly what about the failing SSL negotiation is causing it to fail. Then you should be able to make configuration changes to Windows that will allow it to succeed. IISCrypto is a great tool to use for this (even for client PCs, despite the "IIS" name).
The following two Windows registry keys govern the cipher_suites values that your PC will use:
HKLM\SOFTWARE\Policies\Microsoft\Cryptography\Configuration\SSL\00010002
HKLM\SYSTEM\CurrentControlSet\Control\Cryptography\Configuration\Local\SSL\00010002
Here's a full writeup of how I investigated and solved an instance of this variety of the Could not create SSL/TLS secure channel problem: http://blog.jonschneider.com/2016/08/fix-ssl-handshaking-error-in-windows.html
Something the original answer didn't have. I added some more code to make it bullet proof.
ServicePointManager.Expect100Continue = true;
ServicePointManager.DefaultConnectionLimit = 9999;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12 | SecurityProtocolType.Ssl3;
The top-voted answer will probably be enough for most people. However, in some circumstances, you could continue getting a "Could not create SSL/TLS secure channel" error even after forcing TLS 1.2. If so, you may want to consult this helpful article for additional troubleshooting steps. To summarize: independent of the TLS/SSL version issue, the client and server must agree on a "cipher suite." During the "handshake" phase of the SSL connection, the client will list its supported cipher-suites for the server to check against its own list. But on some Windows machines, certain common cipher-suites may have been disabled (seemingly due to well-intentioned attempts to limit attack surface), decreasing the possibility of the client & server agreeing on a cipher suite. If they cannot agree, then you may see "fatal alert code 40" in the event viewer and "Could not create SSL/TLS secure channel" in your .NET program.
The aforementioned article explains how to list all of a machine's potentially-supported cipher suites and enable additional cipher suites through the Windows Registry. To help check which cipher suites are enabled on the client, try visiting this diagnostic page in MSIE. (Using System.Net tracing may give more definitive results.) To check which cipher suites are supported by the server, try this online tool (assuming that the server is Internet-accessible). It should go without saying that Registry edits must be done with caution, especially where networking is involved. (Is your machine a remote-hosted VM? If you were to break networking, would the VM be accessible at all?)
In my company's case, we enabled several additional "ECDHE_ECDSA" suites via Registry edit, to fix an immediate problem and guard against future problems. But if you cannot (or will not) edit the Registry, then numerous workarounds (not necessarily pretty) come to mind. For example: your .NET program could delegate its SSL traffic to a separate Python program (which may itself work, for the same reason that Chrome requests may succeed where MSIE requests fail on an affected machine).
This one is working for me in MVC webclient
public string DownloadSite(string RefinedLink)
{
try
{
Uri address = new Uri(RefinedLink);
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
using (WebClient webClient = new WebClient())
{
var stream = webClient.OpenRead(address);
using (StreamReader sr = new StreamReader(stream))
{
var page = sr.ReadToEnd();
return page;
}
}
}
catch (Exception e)
{
log.Error("DownloadSite - error Lin = " + RefinedLink, e);
return null;
}
}
"The request was aborted: Could not create SSL/TLS secure channel" exception can occur if the server is returning an HTTP 401 Unauthorized response to the HTTP request.
You can determine if this is happening by turning on trace-level System.Net logging for your client application, as described in this answer.
Once that logging configuration is in place, run the application and reproduce the error, then look in the logging output for a line like this:
System.Net Information: 0 : [9840] Connection#62912200 - Received status line: Version=1.1, StatusCode=401, StatusDescription=Unauthorized.
In my situation, I was failing to set a particular cookie that the server was expecting, leading to the server responding to the request with the 401 error, which in turn led to the "Could not create SSL/TLS secure channel" exception.
Another possibility is improper certificate importation on the box. Make sure to select encircled check box. Initially I didn't do it, so code was either timing out or throwing same exception as private key could not be located.
I had this problem because my web.config had:
<httpRuntime targetFramework="4.5.2" />
and not:
<httpRuntime targetFramework="4.6.1" />
Doing this helped me:
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
Finally found solution for me.
Try this adding below line before calling https url (for .Net framework 4.5):
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
As you can tell there are plenty of reasons this might happen. Thought I would add the cause I encountered ...
If you set the value of WebRequest.Timeout to 0, this is the exception that is thrown. Below is the code I had... (Except instead of a hard-coded 0 for the timeout value, I had a parameter which was inadvertently set to 0).
WebRequest webRequest = WebRequest.Create(#"https://myservice/path");
webRequest.ContentType = "text/html";
webRequest.Method = "POST";
string body = "...";
byte[] bytes = Encoding.ASCII.GetBytes(body);
webRequest.ContentLength = bytes.Length;
var os = webRequest.GetRequestStream();
os.Write(bytes, 0, bytes.Length);
os.Close();
webRequest.Timeout = 0; //setting the timeout to 0 causes the request to fail
WebResponse webResponse = webRequest.GetResponse(); //Exception thrown here ...
The root of this exception in my case was that at some point in code the following was being called:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
This is really bad. Not only is it instructing .NET to use an insecure protocol, but this impacts every new WebClient (and similar) request made afterward within your appdomain. (Note that incoming web requests are unaffected in your ASP.NET app, but new WebClient requests, such as to talk to an external web service, are).
In my case, it was not actually needed, so I could just delete the statement and all my other web requests started working fine again. Based on my reading elsewhere, I learned a few things:
This is a global setting in your appdomain, and if you have concurrent activity, you can't reliably set it to one value, do your action, and then set it back. Another action may take place during that small window and be impacted.
The correct setting is to leave it default. This allows .NET to continue to use whatever is the most secure default value as time goes on and you upgrade frameworks. Setting it to TLS12 (which is the most secure as of this writing) will work now but in 5 years may start causing mysterious problems.
If you really need to set a value, you should consider doing it in a separate specialized application or appdomain and find a way to talk between it and your main pool. Because it's a single global value, trying to manage it within a busy app pool will only lead to trouble. This answer: https://stackoverflow.com/a/26754917/7656 provides a possible solution by way of a custom proxy. (Note I have not personally implemented it.)
In my case, the service account running the application did not have permission to access the private key. Once I gave this permission, the error went away
mmc
certificates
Expand to personal
select cert
right click
All tasks
Manage private keys
Add the service account user
If you are running your code from Visual Studio, try running Visual Studio as administrator. Fixed the issue for me.
System.Net.WebException: The request was aborted: Could not create
SSL/TLS secure channel.
In our case, we where using a software vendor so we didn't have access to modify the .NET code. Apparently .NET 4 won't use TLS v 1.2 unless there is a change.
The fix for us was adding the SchUseStrongCrypto key to the registry. You can copy/paste the below code into a text file with the .reg extension and execute it. It served as our "patch" to the problem.
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v4.0.30319]
"SchUseStrongCrypto"=dword:00000001
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319]
"SchUseStrongCrypto"=dword:00000001
I have struggled with this problem all day.
When I created a new project with .NET 4.5 I finally got it to work.
But if I downgraded to 4.0 I got the same problem again, and it was irreversable for that project (even when i tried to upgrade to 4.5 again).
Strange no other error message but "The request was aborted: Could not create SSL/TLS secure channel." came up for this error
In case that the client is a windows machine, a possible reason could be that the tls or ssl protocol required by the service is not activated.
This can be set in:
Control Panel -> Network and Internet -> Internet Options -> Advanced
Scroll settings down to "Security" and choose between
Use SSL 2.0
Use SSL 3.0
Use TLS 1.0
Use TLS 1.1
Use TLS 1.2
none of this answer not working for me , the google chrome and postman work and handshake the server but ie and .net not working. in google chrome in security tab > connection show that encrypted and authenticated using ECDHE_RSA with P-256 and AES_256_GCM cipher suite to handshake with the server.
i install IIS Crypto and in cipher suites list on windows server 2012 R2 ican't find ECDHE_RSA with P-256 and AES_256_GCM cipher suite. then i update windows to the last version but the problem not solve. finally after searches i understood that windows server 2012 R2 not support GSM correctly and update my server to windows server 2016 and my problem solved.
I was having this same issue and found this answer worked properly for me. The key is 3072. This link provides the details on the '3072' fix.
ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;
XmlReader r = XmlReader.Create(url);
SyndicationFeed albums = SyndicationFeed.Load(r);
In my case two feeds required the fix:
https://www.fbi.gov/feeds/fbi-in-the-news/atom.xml
https://www.wired.com/feed/category/gear/latest/rss
None of the answers worked for me.
This is what worked:
Instead of initializing my X509Certifiacte2 like this:
var certificate = new X509Certificate2(bytes, pass);
I did it like this:
var certificate = new X509Certificate2(bytes, pass, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable);
Notice the X509KeyStorageFlags.Exportable !!
I didn't change the rest of the code (the WebRequest itself):
// I'm not even sure the first two lines are necessary:
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
request = (HttpWebRequest)WebRequest.Create(string.Format("https://{0}.sii.cl/cvc_cgi/dte/of_solicita_folios", server));
request.Method = "GET";
request.Referer = string.Format("https://hercules.sii.cl/cgi_AUT2000/autInicio.cgi?referencia=https://{0}.sii.cl/cvc_cgi/dte/of_solicita_folios", servidor);
request.UserAgent = "Mozilla/4.0";
request.ClientCertificates.Add(certificate);
request.CookieContainer = new CookieContainer();
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
// etc...
}
In fact I'm not even sure that the first two lines are necessary...
Another possibility is that the code being executed doesn't have the required permissions.
In my case, I got this error when using Visual Studio debugger to test a call to a web service. Visual Studio wasn't running as Administrator, which caused this exception.
This fixed for me, add Network Service to permissions.
Right click on the certificate > All Tasks > Manage Private Keys... > Add... > Add "Network Service".
As mentioned in this post, I have exactly the same error in network logs (returned code=AlgorithmMismatch) except I use
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12
to avoid POODLE vulnerability, the regkey has been set to 1 (..\Protocols\SSL 2.0\Client) but I still get this error. My production SSL certificate has been added to Firefox and the secure webservice is reachable and works fine. I precise this error occurs on two environments (Windows Server 2012 and Windows 7) and with a test SSL certificate everything works fine. Any ideas?
..\Protocols\SSL 2.0\Client
That's the wrong key to enable TLS1.2 (SSL *4** was renamed to TLS1.0 while in development, SSL2 is much older, fundamentally broken, and should never be used).
The right keys are given in the MS KB page: https://support.microsoft.com/en-gb/kb/245030
But you'll need to set values in keys including:
…\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server
(And there are plenty of simplified guides to setting things up.)
Even if both client and server can agree on a TLS1.2 protocol suite there are still issues that will lead to failure to create the secure channel (eg. client does not trust the server's certificate). That will need more details (start with the exception type and message, and also for an inner exceptions recursively).
I have a server app and sometimes, when the client tries to connect, I get the following error:
NOTE: the "couldn't get stream from client or login failed" is a text that's added by me in catch statement
and the line at which it stops ( sThread : line 96 ) is :
tcpClient = (TcpClient)client;
clientStream = tcpClient.GetStream();
sr = new StreamReader(clientStream);
sw = new StreamWriter(clientStream);
// line 96:
a = sr.ReadLine();
What may be causing this problem? Note that it doesn't happen all the time
I received this error when calling a web-service. The issue was also related to transport level security. I could call the web-service through a website project, but when reusing the same code in a test project I would get a WebException that contained this message. Adding the following line before making the call resolved the issue:
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
Edit
System.Net.ServicePointManager.SecurityProtocol - This property
selects the version of the Secure Sockets Layer (SSL) or Transport
Layer Security (TLS) protocol to use for new connections that use the
Secure Hypertext Transfer Protocol (HTTPS) scheme only; existing
connections are not changed.
I believe the SecurityProtocol configuration is important during the TLS handshake when selecting the protocol version.
TLS handshake - This protocol is used to exchange all the information required by both sides for the exchange of the actual application data by TLS.
ClientHello - A client sends a ClientHello message specifying the highest TLS protocol version it supports ...
ServerHello - The server responds with a ServerHello message, containing the chosen protocol version ... The chosen protocol version should be the highest that both the client and server support. For example, if the client supports TLS version 1.1 and the server supports version 1.2, version 1.1 should be selected; version 1.2 should not be selected.
This error usually means that the target machine is running, but the service that you're trying to connect to is not available. (Either it stopped, crashed, or is busy with another request.)
In English:
The connection to the machine (remote host/server/PC that the service runs at) was made but since the service was not available on that machine, the machine didn't know what to do with the request.
If the connection to the machine was not available, you'd see a different error. I forget what it is, but it's along the lines of "Service Unreachable" or "Unavailable".
Edit - added
It IS possible that this is being caused by a firewall blocking the port, but given that you say it's intermittent ("sometimes when the client tries to connect"), that's very unlikely. I didn't include that originally because I had ruled it out mentally before replying.
My specific case scenario was that the Azure app service had the minimum TLS version changed to 1.2
I don't know if that's the default from now on, but changing it back to 1.0 made it work.
You can access the setting inside "SSL Settings".
According to "Hans Vonn" replies.
Adding the following line before making the call resolved the issue:
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
After adding Security protocol and working fine but I have to add before every API call which is not healthy. I just upgrade .net framework version at least 4.6 and working as expected do not require to adding before every API call.
Not sure which of the fixes in these blog posts helped, but one of them sorted this issue for me ...
http://briancaos.wordpress.com/2012/07/06/unable-to-read-data-from-the-transport-connection-the-connection-was-closed/
The trick that helped me was to quit using a WebRequest and use a HttpWebRequest instead. The HttpWebRequest allows me to play with 3 important settings:
and
http://briancaos.wordpress.com/2012/06/15/an-existing-connection-was-forcibly-closed-by-the-remote-host/
STEP 1: Disable KeepAlive
STEP 2: Set ProtocolVersion to Version10
STEP 3: Limiting the number of service points
For those who may find this later, after .NET version 4.6, I was running into this problem as well.
Make sure that you check your web.config file for the following lines:
<compilation debug="true" targetFramework="4.5">
...
<httpRuntime targetFramework="4.5" />
If you are running 4.6.x or a higher version of .NET on the server, make sure you adjust these targetFramework values to match the version of the framework on your server. If your versions read less than 4.6.x, then I would recommend you upgrade .NET and use the newer version unless your code is dependent on an older version (which, in that case, you should consider updating it).
I changed the targetFrameworks to 4.7.2 and the problem disappeared:
<compilation debug="true" targetFramework="4.7.2">
...
<httpRuntime targetFramework="4.7.2" />
The newer frameworks sort this issue out by using the best protocol available and blocking insecure or obsolete ones. If the remote service you are trying to connect to or call is giving this error, it could be that they don't support the old protocols anymore.
Calls to HTTPS services from one of our servers were also throwing the "Unable to read data from the transport connection : An existing connection was forcibly closed" exception. HTTP service, though, worked fine. Used Wireshark to see that it was a TLS handshake Failure. Ended up being that the cipher suite on the server needed to be updated.
This solved my problem. I added this line before the request is made:
System.Net.ServicePointManager.Expect100Continue = false;
It seemed there were a proxy in the way of the server that not supported 100-continue behavior.
This won't help for intermittent issues, but may be useful for other people with a similar problem.
I had cloned a VM and started it up on a different network with a new IP address but not changed the bindings in IIS. Fiddler was showing me "Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host" and IE was telling me "Turn on TLS 1.0, TLS 1.1, and TLS 1.2 in Advanced settings". Changing the binding to the new IP address solved it for me.
For some reason, the connection to the server was lost. It could be that the server explicitly closed the connection, or a bug on the server caused it to be closed unexpectedly. Or something between the client and the server (a switch or router) dropped the connection.
It might be server code that caused the problem, and it might not be. If you have access to the server code, you can put some debugging in there to tell you when client connections are closed. That might give you some indication of when and why connections are being dropped.
On the client, you have to write your code to take into account the possibility of the server failing at any time. That's just the way it is: network connections are inherently unreliable.
I was sending the HttpWebRequest from Console App, and UserAgent was
null by (default), so setting UserAgent worked along with setting
SecurityProtocol.
Should set SecurityProtocol before creating HttpWebRequest.
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
HttpWebRequest req = (HttpWebRequest)WebRequest.Create("yourpostURL");
req.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36";
The webrequest user agent is null by default. Just google "block empty user agent" and you'll find a strong desire of many web server admins to do just that.
Sending my request with
request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0";
fixed the issue.
I get that problem in the past. I'm using PostgreSQL and when I run my program, sometimes it connects and sometimes it throws an error like that.
When I experiment with my code, I put my Connection code at the very first line below the public Form. Here is an example:
BEFORE:
public Form1()
{
//HERE LIES SOME CODES FOR RESIZING MY CONTROLS DURING RUNTIME
//CODE
//CODE AGAIN
//ANOTHER CODE
//CODE NA NAMAN
//CODE PA RIN!
//Connect to Database to generate auto number
NpgsqlConnection iConnect = new NpgsqlConnection("Server=localhost;Port=5432;User ID=postgres;Password=pass;Database=DB");
iConnect.Open();
NpgsqlCommand iQuery = new NpgsqlCommand("Select * from table1", iConnect);
NpgsqlDataReader iRead = iQuery.ExecuteReader();
NpgsqlDataAdapter iAdapter = new NpgsqlDataAdapter(iQuery);
DataSet iDataSet = new DataSet();
iAdapter.Fill(iDataSet, "ID");
MessageBox.Show(iDataSet.Tables["ID"].Rows.Count.ToString());
}
NOW:
public Form1()
{
//Connect to Database to generate auto number
NpgsqlConnection iConnect = new NpgsqlConnection("Server=localhost;Port=5432;User ID=postgres;Password=pass;Database=DB");
iConnect.Open();
NpgsqlCommand iQuery = new NpgsqlCommand("Select * from table1", iConnect);
NpgsqlDataReader iRead = iQuery.ExecuteReader();
NpgsqlDataAdapter iAdapter = new NpgsqlDataAdapter(iQuery);
DataSet iDataSet = new DataSet();
iAdapter.Fill(iDataSet, "ID");
MessageBox.Show(iDataSet.Tables["ID"].Rows.Count.ToString());
//HERE LIES SOME CODES FOR RESIZING MY CONTROLS DURING RUNTIME
//CODE
//CODE AGAIN
//ANOTHER CODE
//CODE NA NAMAN
//CODE PA RIN!
}
I think that the program must read first the connection before doing anything, I don't know, correct me if I'm wrong. But according to my research, it's not a code problem - it was actually from the machine itself.
System.Net.ServicePointManager.Expect100Continue = false;
This issue sometime occurs due the reason of proxy server implemented on web server. To bypass the proxy server by putting this line before calling the send service.
We had a very similar issue whereby a client's website was trying to connect to our Web API service and getting that same message. This started happening completely out of the blue when there had been no code changes or Windows updates on the server where IIS was running.
In our case it turned out that the calling website was using a version of .Net that only supported TLS 1.0 and for some reason the server where our IIS was running stopped appeared to have stopped accepting TLS 1.0 calls. To diagnose that we had to explicitly enable TLS via the registry on the IIS's server and then restart that server. These are the reg keys:
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS
1.0\Client] "DisabledByDefault"=dword:00000000 "Enabled"=dword:00000001
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS
1.0\Server] "DisabledByDefault"=dword:00000000 "Enabled"=dword:00000001
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS
1.1\Client] "DisabledByDefault"=dword:00000000 "Enabled"=dword:00000001
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS
1.1\Server] "DisabledByDefault"=dword:00000000 "Enabled"=dword:00000001
[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
If that doesn't do it, you could also experiment with adding the entry for SSL 2.0:
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 2.0\Client]
"DisabledByDefault"=dword:00000000
"Enabled"=dword:00000001
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 2.0\Server]
"DisabledByDefault"=dword:00000000
"Enabled"=dword:00000001
My answer to another question here has this powershell script that we used to add the entries:
NOTE: Enabling old security protocols is not a good idea, the right answer in our case was to get the client website to update it's code to use TLS 1.2, but the registry entries above can help diagnose the issue in the first place.
The reason this was happening to me was I had a recursive dependency in my DI provider. In my case I had:
services.AddScoped(provider => new CfDbContext(builder.Options));
services.AddScoped(provider => provider.GetService<CfDbContext>());
Fix was to just remove the second scoped service registration
services.AddScoped(provider => new CfDbContext(builder.Options));
Had a similar problem and was getting the following errors depending on what app I used and if we bypassed the firewall / load balancer or not:
HTTPS handshake to [blah] (for #136) failed.
System.IO.IOException Unable to read data from the transport
connection: An existing connection was forcibly closed by the remote
host
and
ReadResponse() failed: The server did not return a complete response for this request. Server returned 0 bytes.
The problem turned out to be that the SSL Server Certificate got missed and wasn't installed on a couple servers.
For me, It was an issue where in the IIS binding it had the IP address of the web server.
I changed it to use all unassigned IPs and my application started to work.
I experienced the error with python clr running mdx query to Microsoft analytic services using adomd
I solved it with help of Hans Vonn and here is the python version:
clr.AddReference("System.Net")
from System.Net import ServicePointManager, SecurityProtocolType
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls
I received this error simply because I was attempting to make an http connection to an https-only server. Changing the request protocol in the URI from http to https thus resolved it.
This is how I solved the issue:
int i = 0;
while (stream.DataAvailable == true)
{
bytes[i] = ((byte)stream.ReadByte());
i++;
}
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
Console.WriteLine("Received: {0}", data);
I had a Third Party application (Fiddler) running to try and see the requests being sent. Closing this application fixed it for me
If you have a https certificate on the domain, make sure you have the https binding to the domain name in IIS.
In IIS -> Select your domain -> Click on Bindings
Site Bindings Window opens up. Add a binding for https.
Try checking if you can establish handshake in the first place. I had this issue before when uploading a file and I only figured out that the issue was the nonexistent route when I removed the upload and checked if it can login given the parameters.
Another option would be to check the error code generated using try-catch block and first catching a WebException.
In my case, the error code was "SendFailure" because of certificate issue on HTTPS url, once I hit HTTP, that got resolved.
https://learn.microsoft.com/en-us/dotnet/api/system.net.webexceptionstatus?redirectedfrom=MSDN&view=netframework-4.8
This problem occurring when the Service is Unavailable within the proxy server. We can bypass the proxy server.
Before start, the service, apply this code line.
System.Net.ServicePointManager.Expect100Continue = false;
Further details
In my case I resolved this problem setting a correct API's url in my application.
It was an error connection between the application and API.
We are unable to connect to an HTTPS server using WebRequest because of this error message:
The request was aborted: Could not create SSL/TLS secure channel.
We know that the server doesn't have a valid HTTPS certificate with the path used, but to bypass this issue, we use the following code that we've taken from another StackOverflow post:
private void Somewhere() {
ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(AlwaysGoodCertificate);
}
private static bool AlwaysGoodCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors policyErrors) {
return true;
}
The problem is that server never validates the certificate and fails with the above error. Does anyone have any idea of what I should do?
I should mention that a colleague and I performed tests a few weeks ago and it was working fine with something similar to what I wrote above. The only "major difference" we've found is that I'm using Windows 7 and he was using Windows XP. Does that change something?
I finally found the answer (I haven't noted my source but it was from a search);
While the code works in Windows XP, in Windows 7, you must add this at the beginning:
// using System.Net;
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
// Use SecurityProtocolType.Ssl3 if needed for compatibility reasons
And now, it works perfectly.
ADDENDUM
As mentioned by Robin French; if you are getting this problem while configuring PayPal, please note that they won't support SSL3 starting by December, 3rd 2018. You'll need to use TLS. Here's Paypal page about it.
The solution to this, in .NET 4.5 is
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
If you don’t have .NET 4.5 then use
ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;
Make sure the ServicePointManager settings are made before the HttpWebRequest is created, else it will not work.
Works:
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls
| SecurityProtocolType.Tls11
| SecurityProtocolType.Tls12
| SecurityProtocolType.Ssl3;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://google.com/api/")
Fails:
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://google.com/api/")
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls
| SecurityProtocolType.Tls11
| SecurityProtocolType.Tls12
| SecurityProtocolType.Ssl3;
Note: Several of the highest voted answers here advise setting ServicePointManager.SecurityProtocol, but Microsoft explicitly advises against doing that. Below, I go into the typical cause of this issue and the best practices for resolving it.
One of the biggest causes of this issue is the active .NET Framework version. The .NET framework runtime version affects which security protocols are enabled by default.
In ASP.NET sites, the framework runtime version is often specified in web.config. (see below)
In other apps, the runtime version is usually the version for which the project was built, regardless of whether it is running on a machine with a newer .NET version.
There doesn't seem to be any authoritative documentation on how it specifically works in different versions, but it seems the defaults are determined more or less as follows:
Framework Version
Default Protocols
4.5 and earlier
SSL 3.0, TLS 1.0
4.6.x
TLS 1.0, 1.1, 1.2, 1.3
4.7+
System (OS) Defaults
For the older versions, your mileage may vary somewhat based on which .NET runtimes are installed on the system. For example, there could be a situation where you are using a very old framework and TLS 1.0 is not supported, or using 4.6.x and TLS 1.3 is not supported.
Microsoft's documentation strongly advises using 4.7+ and the system defaults:
We recommend that you:
Target .NET Framework 4.7 or later versions on your apps. Target .NET Framework 4.7.1 or later versions on your WCF apps.
Do not specify the TLS version. Configure your code to let the OS decide on the TLS version.
Perform a thorough code audit to verify you're not specifying a TLS or SSL version.
For ASP.NET sites: check the targetFramework version in your <httpRuntime> element, as this (when present) determines which runtime is actually used by your site:
<httpRuntime targetFramework="4.5" />
Better:
<httpRuntime targetFramework="4.7" />
I had this problem trying to hit https://ct.mob0.com/Styles/Fun.png, which is an image distributed by CloudFlare on its CDN that supports crazy stuff like SPDY and weird redirect SSL certs.
Instead of specifying Ssl3 as in Simons answer I was able to fix it by going down to Tls12 like this:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
new WebClient().DownloadData("https://ct.mob0.com/Styles/Fun.png");
The problem you're having is that the aspNet user doesn't have access to the certificate. You have to give access using the winhttpcertcfg.exe
An example on how to set this up is at:
http://support.microsoft.com/kb/901183
Under step 2 in more information
EDIT: In more recent versions of IIS, this feature is built in to the certificate manager tool - and can be accessed by right clicking on the certificate and using the option for managing private keys. More details here: https://serverfault.com/questions/131046/how-to-grant-iis-7-5-access-to-a-certificate-in-certificate-store/132791#132791
After many long hours with this same issue I found that the ASP.NET account the client service was running under didn't have access to the certificate. I fixed it by going into the IIS Application Pool that the web app runs under, going into Advanced Settings, and changing the Identity to the LocalSystem account from NetworkService.
A better solution is to get the certificate working with the default NetworkService account but this works for quick functional testing.
The error is generic and there are many reasons why the SSL/TLS negotiation may fail. The most common is an invalid or expired server certificate, and you took care of that by providing your own server certificate validation hook, but is not necessarily the only reason. The server may require mutual authentication, it may be configured with a suites of ciphers not supported by your client, it may have a time drift too big for the handshake to succeed and many more reasons.
The best solution is to use the SChannel troubleshooting tools set. SChannel is the SSPI provider responsible for SSL and TLS and your client will use it for the handshake. Take a look at TLS/SSL Tools and Settings.
Also see How to enable Schannel event logging.
The approach with setting
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12
Seems to be okay, because Tls1.2 is latest version of secure protocol. But I decided to look deeper and answer do we really need to hardcode it.
Specs: Windows Server 2012R2 x64.
From the internet there is told that .NetFramework 4.6+ must use Tls1.2 by default. But when I updated my project to 4.6 nothing happened.
I have found some info that tells I need manually do some changes to enable Tls1.2 by default
https://support.microsoft.com/en-in/help/3140245/update-to-enable-tls-1-1-and-tls-1-2-as-default-secure-protocols-in-wi
But proposed windows update doesnt work for R2 version
But what helped me is adding 2 values to registry. You can use next PS script so they will be added automatically
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NetFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -Value '1' -Type DWord
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\.NetFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -Value '1' -Type DWord
That is kind of what I was looking for. But still I cant answer on question why NetFramework 4.6+ doesn't set this ...Protocol value automatically?
Another possible cause of the The request was aborted: Could not create SSL/TLS secure channel error is a mismatch between your client PC's configured cipher_suites values, and the values that the server is configured as being willing and able to accept. In this case, when your client sends the list of cipher_suites values that it is able to accept in its initial SSL handshaking/negotiation "Client Hello" message, the server sees that none of the provided values are acceptable, and may return an "Alert" response instead of proceeding to the "Server Hello" step of the SSL handshake.
To investigate this possibility, you can download Microsoft Message Analyzer, and use it to run a trace on the SSL negotiation that occurs when you try and fail to establish an HTTPS connection to the server (in your C# app).
If you are able to make a successful HTTPS connection from another environment (e.g. the Windows XP machine that you mentioned -- or possibly by hitting the HTTPS URL in a non-Microsoft browser that doesn't use the OS's cipher suite settings, such as Chrome or Firefox), run another Message Analyzer trace in that environment to capture what happens when the SSL negotiation succeeds.
Hopefully, you'll see some difference between the two Client Hello messages that will allow you to pinpoint exactly what about the failing SSL negotiation is causing it to fail. Then you should be able to make configuration changes to Windows that will allow it to succeed. IISCrypto is a great tool to use for this (even for client PCs, despite the "IIS" name).
The following two Windows registry keys govern the cipher_suites values that your PC will use:
HKLM\SOFTWARE\Policies\Microsoft\Cryptography\Configuration\SSL\00010002
HKLM\SYSTEM\CurrentControlSet\Control\Cryptography\Configuration\Local\SSL\00010002
Here's a full writeup of how I investigated and solved an instance of this variety of the Could not create SSL/TLS secure channel problem: http://blog.jonschneider.com/2016/08/fix-ssl-handshaking-error-in-windows.html
Something the original answer didn't have. I added some more code to make it bullet proof.
ServicePointManager.Expect100Continue = true;
ServicePointManager.DefaultConnectionLimit = 9999;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12 | SecurityProtocolType.Ssl3;
The top-voted answer will probably be enough for most people. However, in some circumstances, you could continue getting a "Could not create SSL/TLS secure channel" error even after forcing TLS 1.2. If so, you may want to consult this helpful article for additional troubleshooting steps. To summarize: independent of the TLS/SSL version issue, the client and server must agree on a "cipher suite." During the "handshake" phase of the SSL connection, the client will list its supported cipher-suites for the server to check against its own list. But on some Windows machines, certain common cipher-suites may have been disabled (seemingly due to well-intentioned attempts to limit attack surface), decreasing the possibility of the client & server agreeing on a cipher suite. If they cannot agree, then you may see "fatal alert code 40" in the event viewer and "Could not create SSL/TLS secure channel" in your .NET program.
The aforementioned article explains how to list all of a machine's potentially-supported cipher suites and enable additional cipher suites through the Windows Registry. To help check which cipher suites are enabled on the client, try visiting this diagnostic page in MSIE. (Using System.Net tracing may give more definitive results.) To check which cipher suites are supported by the server, try this online tool (assuming that the server is Internet-accessible). It should go without saying that Registry edits must be done with caution, especially where networking is involved. (Is your machine a remote-hosted VM? If you were to break networking, would the VM be accessible at all?)
In my company's case, we enabled several additional "ECDHE_ECDSA" suites via Registry edit, to fix an immediate problem and guard against future problems. But if you cannot (or will not) edit the Registry, then numerous workarounds (not necessarily pretty) come to mind. For example: your .NET program could delegate its SSL traffic to a separate Python program (which may itself work, for the same reason that Chrome requests may succeed where MSIE requests fail on an affected machine).
This one is working for me in MVC webclient
public string DownloadSite(string RefinedLink)
{
try
{
Uri address = new Uri(RefinedLink);
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
using (WebClient webClient = new WebClient())
{
var stream = webClient.OpenRead(address);
using (StreamReader sr = new StreamReader(stream))
{
var page = sr.ReadToEnd();
return page;
}
}
}
catch (Exception e)
{
log.Error("DownloadSite - error Lin = " + RefinedLink, e);
return null;
}
}
"The request was aborted: Could not create SSL/TLS secure channel" exception can occur if the server is returning an HTTP 401 Unauthorized response to the HTTP request.
You can determine if this is happening by turning on trace-level System.Net logging for your client application, as described in this answer.
Once that logging configuration is in place, run the application and reproduce the error, then look in the logging output for a line like this:
System.Net Information: 0 : [9840] Connection#62912200 - Received status line: Version=1.1, StatusCode=401, StatusDescription=Unauthorized.
In my situation, I was failing to set a particular cookie that the server was expecting, leading to the server responding to the request with the 401 error, which in turn led to the "Could not create SSL/TLS secure channel" exception.
Another possibility is improper certificate importation on the box. Make sure to select encircled check box. Initially I didn't do it, so code was either timing out or throwing same exception as private key could not be located.
I had this problem because my web.config had:
<httpRuntime targetFramework="4.5.2" />
and not:
<httpRuntime targetFramework="4.6.1" />
Doing this helped me:
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
Finally found solution for me.
Try this adding below line before calling https url (for .Net framework 4.5):
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
As you can tell there are plenty of reasons this might happen. Thought I would add the cause I encountered ...
If you set the value of WebRequest.Timeout to 0, this is the exception that is thrown. Below is the code I had... (Except instead of a hard-coded 0 for the timeout value, I had a parameter which was inadvertently set to 0).
WebRequest webRequest = WebRequest.Create(#"https://myservice/path");
webRequest.ContentType = "text/html";
webRequest.Method = "POST";
string body = "...";
byte[] bytes = Encoding.ASCII.GetBytes(body);
webRequest.ContentLength = bytes.Length;
var os = webRequest.GetRequestStream();
os.Write(bytes, 0, bytes.Length);
os.Close();
webRequest.Timeout = 0; //setting the timeout to 0 causes the request to fail
WebResponse webResponse = webRequest.GetResponse(); //Exception thrown here ...
The root of this exception in my case was that at some point in code the following was being called:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
This is really bad. Not only is it instructing .NET to use an insecure protocol, but this impacts every new WebClient (and similar) request made afterward within your appdomain. (Note that incoming web requests are unaffected in your ASP.NET app, but new WebClient requests, such as to talk to an external web service, are).
In my case, it was not actually needed, so I could just delete the statement and all my other web requests started working fine again. Based on my reading elsewhere, I learned a few things:
This is a global setting in your appdomain, and if you have concurrent activity, you can't reliably set it to one value, do your action, and then set it back. Another action may take place during that small window and be impacted.
The correct setting is to leave it default. This allows .NET to continue to use whatever is the most secure default value as time goes on and you upgrade frameworks. Setting it to TLS12 (which is the most secure as of this writing) will work now but in 5 years may start causing mysterious problems.
If you really need to set a value, you should consider doing it in a separate specialized application or appdomain and find a way to talk between it and your main pool. Because it's a single global value, trying to manage it within a busy app pool will only lead to trouble. This answer: https://stackoverflow.com/a/26754917/7656 provides a possible solution by way of a custom proxy. (Note I have not personally implemented it.)
In my case, the service account running the application did not have permission to access the private key. Once I gave this permission, the error went away
mmc
certificates
Expand to personal
select cert
right click
All tasks
Manage private keys
Add the service account user
If you are running your code from Visual Studio, try running Visual Studio as administrator. Fixed the issue for me.
System.Net.WebException: The request was aborted: Could not create
SSL/TLS secure channel.
In our case, we where using a software vendor so we didn't have access to modify the .NET code. Apparently .NET 4 won't use TLS v 1.2 unless there is a change.
The fix for us was adding the SchUseStrongCrypto key to the registry. You can copy/paste the below code into a text file with the .reg extension and execute it. It served as our "patch" to the problem.
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v4.0.30319]
"SchUseStrongCrypto"=dword:00000001
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319]
"SchUseStrongCrypto"=dword:00000001
I have struggled with this problem all day.
When I created a new project with .NET 4.5 I finally got it to work.
But if I downgraded to 4.0 I got the same problem again, and it was irreversable for that project (even when i tried to upgrade to 4.5 again).
Strange no other error message but "The request was aborted: Could not create SSL/TLS secure channel." came up for this error
In case that the client is a windows machine, a possible reason could be that the tls or ssl protocol required by the service is not activated.
This can be set in:
Control Panel -> Network and Internet -> Internet Options -> Advanced
Scroll settings down to "Security" and choose between
Use SSL 2.0
Use SSL 3.0
Use TLS 1.0
Use TLS 1.1
Use TLS 1.2
none of this answer not working for me , the google chrome and postman work and handshake the server but ie and .net not working. in google chrome in security tab > connection show that encrypted and authenticated using ECDHE_RSA with P-256 and AES_256_GCM cipher suite to handshake with the server.
i install IIS Crypto and in cipher suites list on windows server 2012 R2 ican't find ECDHE_RSA with P-256 and AES_256_GCM cipher suite. then i update windows to the last version but the problem not solve. finally after searches i understood that windows server 2012 R2 not support GSM correctly and update my server to windows server 2016 and my problem solved.
I was having this same issue and found this answer worked properly for me. The key is 3072. This link provides the details on the '3072' fix.
ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;
XmlReader r = XmlReader.Create(url);
SyndicationFeed albums = SyndicationFeed.Load(r);
In my case two feeds required the fix:
https://www.fbi.gov/feeds/fbi-in-the-news/atom.xml
https://www.wired.com/feed/category/gear/latest/rss
None of the answers worked for me.
This is what worked:
Instead of initializing my X509Certifiacte2 like this:
var certificate = new X509Certificate2(bytes, pass);
I did it like this:
var certificate = new X509Certificate2(bytes, pass, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable);
Notice the X509KeyStorageFlags.Exportable !!
I didn't change the rest of the code (the WebRequest itself):
// I'm not even sure the first two lines are necessary:
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
request = (HttpWebRequest)WebRequest.Create(string.Format("https://{0}.sii.cl/cvc_cgi/dte/of_solicita_folios", server));
request.Method = "GET";
request.Referer = string.Format("https://hercules.sii.cl/cgi_AUT2000/autInicio.cgi?referencia=https://{0}.sii.cl/cvc_cgi/dte/of_solicita_folios", servidor);
request.UserAgent = "Mozilla/4.0";
request.ClientCertificates.Add(certificate);
request.CookieContainer = new CookieContainer();
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
// etc...
}
In fact I'm not even sure that the first two lines are necessary...
Another possibility is that the code being executed doesn't have the required permissions.
In my case, I got this error when using Visual Studio debugger to test a call to a web service. Visual Studio wasn't running as Administrator, which caused this exception.
This fixed for me, add Network Service to permissions.
Right click on the certificate > All Tasks > Manage Private Keys... > Add... > Add "Network Service".