The client and server cannot communicate, because they do not possess a common algorithm - ASP.NET C# IIS TLS 1.0 / 1.1 / 1.2 - Win32Exception

I have an issue with a C# PayTrace Gateway. The below code was working fine until yesterday when I believe they turned off SSL3 due to the Poodle Exploit. When running the code below we got the following message. The remote server has forcefully closed the connection. After doing some research on the problem we determined that because our IIS Server 7.5 was configured to still use SSL3, C# defaulted to SSL3, which PayTrace would forcibly close the connection. We then removed SSL3 from the server. Which then lead to the following error:

The client and server cannot communicate, because they do not possess a common algorithm.

My guess is that there are additional SSL algorithm we need to install on the server now that SSL 3 is removed. Our IT staff claims that TLS 1.1 and TLS 1.2 are working and that ASP.NET should be now defaulting to those. But I feel like there still must be something else we need to install on the server, I have no knowledge of SSL Algorithms so I have no idea where to begin.

var postUrl = new StringBuilder();

//Initialize url with configuration and parameter values...
postUrl.AppendFormat("UN~{0}|", this.MerchantLoginID);
postUrl.AppendFormat("PSWD~{0}|", this.MerchantTransactionKey);
postUrl.Append("TERMS~Y|METHOD~ProcessTranx|TRANXTYPE~Sale|"); 
postUrl.AppendFormat("CC~{0}|", cardNumber);
postUrl.AppendFormat("EXPMNTH~{0}|", expirationMonth.PadLeft(2, '0'));
postUrl.AppendFormat("EXPYR~{0}|", expirationYear);
postUrl.AppendFormat("AMOUNT~{0}|", transactionAmount);
postUrl.AppendFormat("BADDRESS~{0}|", this.AddressLine1);
postUrl.AppendFormat("BADDRESS2~{0}|", this.AddressLine2);
postUrl.AppendFormat("BCITY~{0}|", this.City);
postUrl.AppendFormat("BSTATE~{0}|", this.State);
postUrl.AppendFormat("BZIP~{0}|", this.Zip);
postUrl.AppendFormat("SADDRESS~{0}|", this.AddressLine1);
postUrl.AppendFormat("SADDRESS2~{0}|", this.AddressLine2);
postUrl.AppendFormat("SCITY~{0}|", this.City);
postUrl.AppendFormat("SSTATE~{0}|", this.State);
postUrl.AppendFormat("SZIP~{0}|", this.Zip);
if (!String.IsNullOrEmpty(this.Country))
{
    postUrl.AppendFormat("BCOUNTRY~{0}|", this.Country);
}
if (!String.IsNullOrEmpty(this.Description))
{
    postUrl.AppendFormat("DESCRIPTION~{0}|", this.Description);
}
if (!String.IsNullOrEmpty(this.InvoiceNumber))
{
    postUrl.AppendFormat("INVOICE~{0}|", this.InvoiceNumber);
}
if (this.IsTestMode)
{
    postUrl.AppendFormat("TEST~Y|");
}

//postUrl.Append();

WebClient wClient = new WebClient();
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;
String sRequest = "PARMLIST=" + Url.Encode(postUrl.ToString());
wClient.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
string sResponse = "";
sResponse = wClient.UploadString(PayTraceUrl, sRequest);

Also, just an FYI, this issue is also happening when we connect to First Data E4 gateway so it's not just a PayTrace thing. My guess is that as more gateways turn off access to SSL3 we'll continue to run into issues with other gateways until this can be resolved on the server. Also, I did find a few suggestions online, some suggested placing the following code right before making the outbound request:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;

Unfortunately that did not work either, same error. Which is why I'm thinking something additional needs to be installed on the IIS7.5 server. I'm just not sure what.


There are several other posts about this now and they all point to enabling TLS 1.2. Anything less is unsafe.

You can do this in .NET 3.5 with a patch.
You can do this in .NET 4.0 and 4.5 with a single line of code

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; // .NET 4.5
ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072; // .NET 4.0

In .NET 4.6, it automatically uses TLS 1.2.

See here for more details: .NET support for TLS.


In my case, even though Target Framework of Project was 4.7.1, I was still getting same Error, Solution was to change httpRuntime in web.config under system.web to 4.7.1!


In a previous answer, it was suggested to use this line of code for .Net 4.5:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; // .NET 4.5

I would encourage you to OR that value in to whatever the existing values are like this:

ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12; // .NET 4.5

If you look at the list of values, you notice that they are a power of two. This way, in the future when things shift to TLS 2.0 for example, your code will still work.


There are two possible scenario, in my case I used 2nd point.

  1. If you are facing this issue in production environment and you can easily deploy new code to the production then you can use of below solution.

    You can add below line of code before making api call,

    ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; // .NET 4.5

  2. If you cannot deploy new code and you want to resolve with the same code which is present in the production, then this issue can be done by changing some configuration setting file. You can add either of one in your config file.

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

or

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

This was resolved. It turns out our IT Staff was correct. Both TLS 1.1 and TLS 1.2 were installed on the server. However, the issue was that our sites are running as ASP.NET 4.0 and you have to have ASP.NET 4.5 to run TLS 1.1 or TLS 1.2. So, to resolve the issue, our IT Staff had to re-enable TLS 1.0 to allow a connection with PayTrace.

So in short, the error message, "the client and server cannot communicate, because they do not possess a common algorithm", was caused because there was no SSL Protocol available on the server to communicate with PayTrace's servers.

UPDATE: Please do not enable TLS 1.0 on your servers, this was a temporary fix and is not longer applicable since there are now better work-arounds that ensure strong security practices. Please see accepted answer for a solution. FYI, I'm going to keep this answer on the site as it provides information on what the problem was, please do not down-vote.