How to add a trusted CA certificate (NOT a client certificate) to HttpWebRequest?

后端 未结 2 1418
盖世英雄少女心
盖世英雄少女心 2021-01-02 10:52

I wrote a C# program that uses HttpWebRequest to connect to an HTTPS site. The GetResponse() method throws an exception:

Sy

相关标签:
2条回答
  • 2021-01-02 11:26

    The solution I ultimately implemented was to write a class implementing ICertificatePolicy with custom validation logic:

    private X509CertificateCollection   _certs;
    private ICertificatePolicy          _defaultPolicy;
    
    public bool CheckValidationResult(ServicePoint svcPoint, X509Certificate cert, WebRequest req, int problem)
    {
        if ((_defaultPolicy != null) && _defaultPolicy.CheckValidationResult(svcPoint, cert, req, problem))
        {
            return true;
        }
    
        foreach (X509Certificate caCert in _certs)
        {
            if (caCert.Equals(cert))
            {
                return true;
            }
        }
    
        return false;
    }
    

    (Error-checking omitted for brevity.)

    _defaultPolicy can be set to ServicePointManager.CertificatePolicy to allow the default certificate store to be used in addition to custom certificates.

    _certs contains the extra certificate(s). It's generated by parsing the PEM file and calling _certs.Add(new X509Certificate(Convert.FromBase64String(base64cert)));

    CertificatePolicy has been obsoleted by ServerCertificateValidationCallback, but I needed to support an old version of .NET.

    0 讨论(0)
  • 2021-01-02 11:47

    Try setting your ServerCertificateValidationCallback to use this:

    public static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
    {
        if (sslPolicyErrors == SslPolicyErrors.None)
        return true;
    
        X509Chain privateChain = new X509Chain();
        privateChain.ChainPolicy.RevocationMode = X509RevocationMode.Offline;
    
        X509Certificate2 cert2 = new X509Certificate2(certificate);
        X509Certificate2 signerCert2 = new X509Certificate2(@"C:\MyCACert.PEM");
    
        privateChain.ChainPolicy.ExtraStore.Add(signerCert2);       
        privateChain.Build(cert2);
    
        bool isValid = true;
    
        foreach (X509ChainStatus chainStatus in privateChain.ChainStatus)
        {
            if (chainStatus.Status != X509ChainStatusFlags.NoError)
            {
                isValid = false;
                break;
            }
        }
    
        return isValid;
    }
    

    I have not had an opportunity to test this, so let me know if you encounter any errors and I'll modify the answer if needed.

    0 讨论(0)
提交回复
热议问题