How to solve "Could not establish trust relationship for the SSL/TLS secure channel with authority"

Viewed 375088

I have a WCF service hosted in IIS 7 using HTTPS. When I browse to this site in Internet Explorer, it works like a charm, this is because I have added the certificate to the local root certificate authority store.

I'm developing on 1 machine, so client and server are same machine. The certificate is self-signed directly from IIS 7 management snap in.

I continually get this error now...

Could not establish trust relationship for the SSL/TLS secure channel with authority.

... when called from client console.

I manually gave myself permissions and network service to the certificate, using findprivatekey and using cacls.exe.

I tried to connect to the service using SOAPUI, and that works, so it must be an issue in my client application, which is code based on what used to work with http.

Where else can I look I seem to have exhausted all possibilities as to why I can't connect?

19 Answers

If you use .net core try this:

client.ClientCredentials.ServiceCertificate.SslCertificateAuthentication =
        new X509ServiceCertificateAuthentication()
        {
            CertificateValidationMode = X509CertificateValidationMode.None,
            RevocationMode = System.Security.Cryptography.X509Certificates.X509RevocationMode.NoCheck
        };

I just wanted to add something to the answer of @NMrt who already pointed out:

you could encounter this error if your client is running the wrong TLS version, for example if the server is only running TLS 1.2.

With Framework 4.7.2, if you do not explicitly configure the target framework in your web.config like this

<system.web>
  <compilation targetFramework="4.7" />
  <httpRuntime targetFramework="4.7" />
</system.web>

your system default security protocols will be ignored and something "lower" might be used instead. In my case Ssl3/Tls instead of Tls13.

  • You can fix this also in code by setting the SecurityProtocol (keeps other protocols working):

    System.Net.ServicePointManager.SecurityProtocol |= System.Net.SecurityProtocolType.Tls12 | System.Net.SecurityProtocolType.Tls11;
    System.Net.ServicePointManager.SecurityProtocol &= ~System.Net.SecurityProtocolType.Ssl3;
    
  • or even by adding registry keys to enable or disable strong crypto

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

This blog post pointed me to the right direction and explains the backgrounds better than I can:

https://www.ryadel.com/en/asp-net-client-server-cannot-comunicate-because-they-possess-common-algorithm-how-to-fix-c-sharp/

If you are using .net core, then during development you can bypass certificate validation by using compiler directives. This way will only validate certificate for release and not for debug:

#if (DEBUG)
        client.ClientCredentials.ServiceCertificate.SslCertificateAuthentication =
                new X509ServiceCertificateAuthentication()
                {
                    CertificateValidationMode = X509CertificateValidationMode.None,
                    RevocationMode = System.Security.Cryptography.X509Certificates.X509RevocationMode.NoCheck
                };   #endif

To help with troubleshooting, you can add this temporarily to log additional info about the cert that's causing the validation failure. I logged it to NLog's txt log but you can create EventLog if you want:

System.Net.ServicePointManager.ServerCertificateValidationCallback += (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) =>
{
    StringBuilder sb = new StringBuilder();
    sb.AppendLine($"  Certificate Subject: {certificate.Subject}");
    sb.AppendLine($"  Certificate Issuer: {certificate.Issuer}");
    sb.AppendLine($"  Certificate CertHash: {certificate.GetCertHashString()}");
    sb.AppendLine($"  Certificate EffectiveDate: {certificate.GetEffectiveDateString()}");
    sb.AppendLine($"  Certificate ExpirationDate: {certificate.GetExpirationDateString()}");
    sb.AppendLine($"  sslPolicyErrors: {sslPolicyErrors.ToString()}");
    sb.AppendLine($"  ChainPolicy:");
    sb.AppendLine($"     Chain revocation flag: {chain.ChainPolicy.RevocationFlag}");
    sb.AppendLine($"     Chain revocation mode: {chain.ChainPolicy.RevocationMode}");
    sb.AppendLine($"     Chain verification flag: {chain.ChainPolicy.VerificationFlags}");
    sb.AppendLine($"     Chain verification time: {chain.ChainPolicy.VerificationTime}");
    sb.AppendLine($"     Chain status length: {chain.ChainStatus.Length}");
    sb.AppendLine($"     Chain application policy count: {chain.ChainPolicy.ApplicationPolicy.Count}");
    sb.AppendLine($"     Chain certificate policy count: {chain.ChainPolicy.CertificatePolicy.Count}");

    sb.AppendLine($"  ChainStatus:");
    foreach (var cs in chain.ChainStatus)
    {
        sb.AppendLine($"     Chain certificate policy count: Status: {cs.Status}, StatusInformation: {cs.StatusInformation}");
    }

    NLog.Common.InternalLogger.Error($"ServerCertificateValidationCallback: {sb}\n");

    return true;
};
Related