我编写了一个使用HttpWebRequest
连接到HTTPS站点的C#程序。 GetResponse()
方法抛出异常:
SystemError:底层连接已关闭:无法建立 SSL / TLS安全通道的信任关系。
我可以使用curl.exe --cacert CAFile.pem
连接到同一个网站。我希望能够使用C#程序中相同的可信CA证书。
如何让HttpWebRequest
使用此CA证书文件(或包含从中解析的证书的X509CertificateCollection
)?
答案 0 :(得分:5)
尝试设置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;
}
我没有机会对此进行测试,所以如果您遇到任何错误请告诉我,如果需要,我会修改答案。
答案 1 :(得分: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。