如何将受信任的CA证书(不是客户端证书)添加到HttpWebRequest?

9
我编写了一个使用 HttpWebRequest 连接到 HTTPS 网站的 C# 程序。但是,GetResponse() 方法会抛出异常:

SystemError: 底层连接已关闭:无法建立 SSL/TLS 安全通道的信任关系。

我能够使用 curl.exe --cacert CAFile.pem 连接到同一网站。我希望能够在 C# 程序中使用相同受信任的 CA 证书。
如何让 HttpWebRequest 使用这个 CA 证书文件(或包含从它解析出的证书的 X509CertificateCollection)?
2个回答

8

尝试将您的ServerCertificateValidationCallback设置为使用以下内容:

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

我没有机会测试这个,所以如果您遇到任何错误,请告诉我,我会根据需要修改答案。


谢谢,明天会试一下。 - ThiefMaster
这不起作用 - 如果没有根证书,它甚至不会被调用。 - João Antunes
实际上,在这种情况下,它可以在没有受信任的CA的情况下工作 - 但只有在使用WebClient时才能使用:https://stackoverflow.com/questions/49909510/https-client-to-connect-to-server-without-trusted-chain-non-trusted-ca-on-azur - João Antunes

1
我最终实现的解决方案是编写一个类,实现ICertificatePolicy并具有自定义验证逻辑:
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;
}

为了简洁起见,错误检查被省略。

_defaultPolicy 可以设置为 ServicePointManager.CertificatePolicy,以允许默认证书存储与自定义证书一起使用。

_certs 包含额外的证书。它是通过解析 PEM 文件并调用 _certs.Add(new X509Certificate(Convert.FromBase64String(base64cert))); 生成的。

CertificatePolicy 已被 ServerCertificateValidationCallback 废弃,但我需要支持旧版本的 .NET。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接