如何使用 C# 验证 SSL 证书
How to validate a SSL certificate with C#
也许你们中的一位可以帮助我回答有关在 .NET 框架中验证证书的问题。不幸的是,我在互联网上的研究中只找到了对我的问题的肤浅答案,但没有确切的解释。
同时我知道我可以使用以下代码检查我的软件证书是否有效。
ServicePointManager.ServerCertificateValidationCallback += ValidateRemoteCertificate;
private bool ValidateRemoteCertificate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors policyErrors)
{
return policyErrors == SslPolicyErrors.None;
}
但我现在想知道微软在这里到底检查了什么?框架执行了哪些检查以生成结果 SslPolicyErrors.None?
例如,根证书是否也在这里验证,它来自哪里?如果是这样,如何?
在您看来,是否仍然有必要(或有用)向这些检查添加我自己的检查,而 .NET Framework 尚未进行这些检查?
这部分只是 的重复,那里的简短答案是您免费获得的支票(没有自定义处理程序,或者已经在您的处理程序之前完成):
- 证书链有效(否则
SslPolicyErrors.RemoteCertificateChainErrors
已设置)
- 证书链接到受信任的根授权机构
- 证书未过期(或来自未来)
- 该证书表明它打算用作 TLS 服务器证书
- 如果在请求中启用了撤销(默认情况下处于关闭状态),则链中的任何证书都不会被撤销。
- 证书适用于您连接的主机名(否则
SslPolicyErrors.RemoteCertificateNameMismatch
已设置)
For example, is the root certificate also validated here and where it comes from?
此处的证书验证使用与 Internet Explorer、Chrome、Edge、Outlook 等相同的根信任列表,在 Windows 中集中管理。 (Firefox 使用不同的根信任列表,该列表仅由 Firefox 管理。)
In your opinion ...
意见问题在 Whosebug 上是题外话。
it still necessary (or useful) to add additionally my own checks to these checks, which the .NET Framework hasn't made yet?
视情况而定。
如果您正在联系您自己的服务器之一,并且您知道证书链的某些内容,您可以添加额外的检查。例如,您可能知道您的服务器使用 Let's Encrypt,并且您在应用程序中嵌入了来自 https://letsencrypt.org/certificates/ 的两个 "Let’s Encrypt Authority X3" 证书,然后您可以固定中间件……您只需要确保在他们转向新的中间体。
private bool ValidateRemoteCertificate(
object sender,
X509Certificate cert,
X509Chain chain,
SslPolicyErrors policyErrors)
{
if (policyErrors != SslPolicyErrors.None)
{
return false;
}
if (chain.ChainElements.Count != 3)
{
return false;
}
byte[] foundCert = chain.ChainElements[1].Certificate.RawData;
return s_letsEncryptX3Direct.SequenceEqual(foundCert) ||
s_letsEncryptX3Cross.SequenceEqual(foundCert);
}
如果您不打算执行额外的检查(或进行自定义日志记录等),那么最好甚至不注册回调,因为内存和 CPU 当没有回调注册。
只需检查链状态。已有描述性消息:
[Test]
public async Task CheckWhatError()
{
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback = ValidateRemoteCertificate;
var client = new HttpClient(handler);
try
{
using (var msg = new HttpRequestMessage(HttpMethod.Get, "https://expired.badssl.com/"))
{
using (var response = await client.SendAsync(msg))
{
// do stuff with the response
}
}
}
catch (Exception ex)
{
throw;
}
}
private bool ValidateRemoteCertificate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors policyErrors)
{
if(policyErrors == SslPolicyErrors.RemoteCertificateChainErrors)
{
foreach(var cs in chain.ChainStatus)
{
Console.WriteLine(cs.StatusInformation);//validation errors here
}
}
return policyErrors == SslPolicyErrors.None;
}
也许你们中的一位可以帮助我回答有关在 .NET 框架中验证证书的问题。不幸的是,我在互联网上的研究中只找到了对我的问题的肤浅答案,但没有确切的解释。
同时我知道我可以使用以下代码检查我的软件证书是否有效。
ServicePointManager.ServerCertificateValidationCallback += ValidateRemoteCertificate;
private bool ValidateRemoteCertificate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors policyErrors)
{
return policyErrors == SslPolicyErrors.None;
}
但我现在想知道微软在这里到底检查了什么?框架执行了哪些检查以生成结果 SslPolicyErrors.None?
例如,根证书是否也在这里验证,它来自哪里?如果是这样,如何?
在您看来,是否仍然有必要(或有用)向这些检查添加我自己的检查,而 .NET Framework 尚未进行这些检查?
这部分只是
- 证书链有效(否则
SslPolicyErrors.RemoteCertificateChainErrors
已设置)- 证书链接到受信任的根授权机构
- 证书未过期(或来自未来)
- 该证书表明它打算用作 TLS 服务器证书
- 如果在请求中启用了撤销(默认情况下处于关闭状态),则链中的任何证书都不会被撤销。
- 证书适用于您连接的主机名(否则
SslPolicyErrors.RemoteCertificateNameMismatch
已设置)
For example, is the root certificate also validated here and where it comes from?
此处的证书验证使用与 Internet Explorer、Chrome、Edge、Outlook 等相同的根信任列表,在 Windows 中集中管理。 (Firefox 使用不同的根信任列表,该列表仅由 Firefox 管理。)
In your opinion ...
意见问题在 Whosebug 上是题外话。
it still necessary (or useful) to add additionally my own checks to these checks, which the .NET Framework hasn't made yet?
视情况而定。
如果您正在联系您自己的服务器之一,并且您知道证书链的某些内容,您可以添加额外的检查。例如,您可能知道您的服务器使用 Let's Encrypt,并且您在应用程序中嵌入了来自 https://letsencrypt.org/certificates/ 的两个 "Let’s Encrypt Authority X3" 证书,然后您可以固定中间件……您只需要确保在他们转向新的中间体。
private bool ValidateRemoteCertificate(
object sender,
X509Certificate cert,
X509Chain chain,
SslPolicyErrors policyErrors)
{
if (policyErrors != SslPolicyErrors.None)
{
return false;
}
if (chain.ChainElements.Count != 3)
{
return false;
}
byte[] foundCert = chain.ChainElements[1].Certificate.RawData;
return s_letsEncryptX3Direct.SequenceEqual(foundCert) ||
s_letsEncryptX3Cross.SequenceEqual(foundCert);
}
如果您不打算执行额外的检查(或进行自定义日志记录等),那么最好甚至不注册回调,因为内存和 CPU 当没有回调注册。
只需检查链状态。已有描述性消息:
[Test]
public async Task CheckWhatError()
{
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback = ValidateRemoteCertificate;
var client = new HttpClient(handler);
try
{
using (var msg = new HttpRequestMessage(HttpMethod.Get, "https://expired.badssl.com/"))
{
using (var response = await client.SendAsync(msg))
{
// do stuff with the response
}
}
}
catch (Exception ex)
{
throw;
}
}
private bool ValidateRemoteCertificate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors policyErrors)
{
if(policyErrors == SslPolicyErrors.RemoteCertificateChainErrors)
{
foreach(var cs in chain.ChainStatus)
{
Console.WriteLine(cs.StatusInformation);//validation errors here
}
}
return policyErrors == SslPolicyErrors.None;
}