ChatGPT解决这个技术问题 Extra ChatGPT

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

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?

If you have control of the creation of the certificates, don't forget about "Alternate Subject Name". Like you could put a wild card in "*.full.domainname.com". See digicert.com/subject-alternative-name.htm

s
sharptooth

As a workaround you could add a handler to the ServicePointManager's ServerCertificateValidationCallback on the client side:

System.Net.ServicePointManager.ServerCertificateValidationCallback +=
    (se, cert, chain, sslerror) =>
        {
            return true;
        };

but be aware that this is not a good practice as it completely ignores the server certificate and tells the service point manager that whatever certificate is fine which can seriously compromise client security. You could refine this and do some custom checking (for certificate name, hash etc). at least you can circumvent problems during development when using test certificates.


I think most public setups will use a purchased cert but during dev use the above code within conditional #if statements. Enterprise devs should generally setup an internal CA server >> technet.microsoft.com/en-us/library/cc875810.aspx
Helped me figure out how to get my SSL WCF call working with Fiddler2 for debugging.
@karank Consider putting it in the Application_Start method in the Global.asax (see stackoverflow.com/a/12507094/1175419). I would strongly recommend using a #if DEBUG compiler directive or something similar as mentioned in Luke's comment.
Awesome! you can use lambda expression as System.Net.ServicePointManager.ServerCertificateValidationCallback += (se, cert, chain, sslerror) => true;
A little extra explanation can be found here : blog.effectivemessaging.com/2015_09_01_archive.html
M
Mike Cheel

When I have this problem it is because the client.config had its endpoints like:

 https://myserver/myservice.svc 

but the certificate was expecting

 https://myserver.mydomain.com/myservice.svc

Changing the endpoints to match the FQDN of the server resolves my problem. I know this is not the only cause of this problem.


I just had this issue again and this time it had to with the wrong certificate being used. It seems like in both cases it has to do with matching up names properly.
My auto generated configuration had <endpoint address="localhost/myservice.svc" changing this to <endpoint address="mymachine.mydoman.com/myservice.svc" resolved this.
This was absolutely my issue and it took me two days to find your answer. +1, I would give you +1000 if I could.
b
blowdart

Your problem arises because you're using a self signed key. The client does not trust this key, nor does the key itself provide a chain to validate or a certificate revocation list.

You have a few options - you can

turn off certificate validation on the client (bad move, man in the middle attacks abound) use makecert to create a root CA and create certificates from that (ok move, but there is still no CRL) create an internal root CA using Windows Certificate Server or other PKI solution then trust that root cert (a bit of a pain to manage) purchase an SSL certificate from one of the trusted CAs (expensive)


Regarding (4), StartSSL will actually give you a free Class 1 certificate that works in all major browsers. They work great for me for my half a dozen low bandwidth sites.
I think #2 on this list...this url might help : blogs.technet.microsoft.com/jhoward/2005/02/02/… "How-to use MakeCert for trusted root certification authority and SSL certificate issuance"
Note: StartCom is no longer trustworthy - and has just been removed from Chrome en.wikipedia.org/wiki/StartCom
R
Romano Zumbé

the first two use lambda, the third uses regular code... hope you find it helpful

            //Trust all certificates
            System.Net.ServicePointManager.ServerCertificateValidationCallback =
                ((sender, certificate, chain, sslPolicyErrors) => true);

            // trust sender
            System.Net.ServicePointManager.ServerCertificateValidationCallback
                = ((sender, cert, chain, errors) => cert.Subject.Contains("YourServerName"));

            // validate cert by calling a function
            ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(ValidateRemoteCertificate);

    // callback used to validate the certificate in an SSL conversation
    private static bool ValidateRemoteCertificate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors policyErrors)
    {
        bool result = false;
        if (cert.Subject.ToUpper().Contains("YourServerName"))
        {
            result = true;
        }

        return result;
    }

//Trust all certificates System.Net.ServicePointManager.ServerCertificateValidationCallback += (se, cert, chain, sslerror) => { return true; }; // trust sender System.Net.ServicePointManager.ServerCertificateValidationCallback += (se, cert, chain, sslerror) => { return cert.Subject.Contains("ca-l-9wfvrm1.ceridian.ca"); };
Any cracker could forge a certificate passing all the above tests. This is unsecure.
G
Gaspa79

A one line solution. Add this anywhere before calling the server on the client side:

System.Net.ServicePointManager.ServerCertificateValidationCallback += delegate { return true; };

This should only be used for testing purposes because the client will skip SSL/TLS security checks.


A brilliant workaround for testing. We are consuming a service whose provider has made security a living hell with a convoluted chain of security certificates and until we can get their wonky certs and chaining to work properly, this workaround is the only thing allowing us to continue development.
J
Jeroen-bart Engelen

I encountered the same problem and I was able to resolve it with two solutions: First, I used the MMC snap-in "Certificates" for the "Computer account" and dragged the self-signed certificate into the "Trusted Root Certification Authorities" folder. This means the local computer (the one that generated the certificate) will now trust that certificate. Secondly I noticed that the certificate was generated for some internal computer name, but the web service was being accessed using another name. This caused a mismatch when validating the certificate. We generated the certificate for computer.operations.local, but accessed the web service using https://computer.internaldomain.companydomain.com. When we switched the URL to the one used to generate the certificate we got no more errors.

Maybe just switching URLs would have worked, but by making the certificate trusted you also avoid the red screen in Internet Explorer where it tells you it doesn't trust the certificate.


This didn't work for me initially. I had to make one modification to the steps above: When dragging the certificate, make sure to hold down the Ctrl key so that the certificate is copied, not moved from Personal/Certificates to Trusted Root Certification Authorities/Certificates.
G
Grzegorz J

If you use .net core try this:

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

Thanks, it works. But it has nothing to do with .net core. It's an universal recipe :)
R
Rahul Rai

Please do following steps:

Open service link in IE. Click on the certificate error mention in address bar and click on View certificates. Check issued to: name. Take the issued name and replace localhost mention in service and client endpoint base address name with A fully qualified domain name (FQDN).

For Example: https://localhost:203/SampleService.svc To https://INL-126166-.groupinfra.com:203/SampleService.svc


Great, thanks for this answer ! Solved the issues without making any code changes.
c
crusy

In addition to the answers above, 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.

You can fix it by using:

// tested in .NET 4.5:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

in my case accepted answer didn't help me, but this one did a trick
This is the only answer which corrected the error in my case.
Also this was the trick that helped me, although with .Net 4.7.2
d
dar0x

I had the same problem. I also had added CA certificates in the local store, but I did in the WRONG way.

Using mmc Console (Start -> Run -> mmc ) you should add Certificates snap-in as Service account (choosing the service account of IIS) or Computer account (it adds for every account on the machine)

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

From here now, you can add certificates of CAs (Trusted Root CAs and Intermediate CAs), and everything will work fine


U
Umesh Bhavsar

I had similar issue with self-signed certificate. I could resolve it by using the certificate name same as FQDN of the server.

Ideally, SSL part should be managed at the server side. Client is not required to install any certificate for SSL. Also, some of the posts mentioned about bypassing the SSL from client code. But I totally disagree with that.


j
j0k

I just dragged the certificate into the "Trusted Root Certification Authorities" folder and voila everything worked nicely.

Oh. And I first added the following from a Administrator Command Prompt:

netsh http add urlacl url=https://+:8732/Servicename user=NT-MYNDIGHET\INTERAKTIV

I am not sure of the name you need for the user (mine is norwegian as you can see !): user=NT-AUTHORITY/INTERACTIVE ?

You can see all existing urlacl's by issuing the command: netsh http show urlacl


p
phifi

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/


l
lko

This occurred when trying to connect to the WCF Service via. the IP e.g. https://111.11.111.1:port/MyService.svc while using a certificate tied to a name e.g. mysite.com.

Switching to the https://mysite.com:port/MyService.svc resolved it.


s
sonia

This occurred when trying to connect to the WCF Service using only host name e.g. https://host/MyService.svc while using a certificate tied to a name e.g. host.mysite.com.

Switching to the https://host.mysite.com/MyService.svc and this resolved it.


A
Alberto

Just fixed a similar issue.

I realized I had an application pool that was running under an account that only had reading permission over the certificate that it was used.

The .NET application could correctly retrieve the certificate but that exception was thrown only when GetRequestStream() was called.

Certificates permissions can be managed via MMC console


P
Panayiotis Hiripis

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

m
metasapien

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;
};

B
Bokambo

Add this to your client code :

ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(
    delegate
    {
        return true;
    });

This answer isn't very good, as it does not explain the risks associated with the code.

关注公众号,不定期副业成功案例分享
Follow WeChat

Success story sharing

Want to stay one step ahead of the latest teleworks?

Subscribe Now