【发布时间】:2021-08-04 11:32:46
【问题描述】:
我正在尝试验证 X509 证书链而不将根 CA 证书导入受信任的根 CA 证书存储(在生产中,此代码将在 Azure 函数中运行,you can't add certificates to the trusted root CA certificate store on Azure App Services)。
我们还需要对此证书链执行在线 CRL 检查。
我对此进行了搜索,发现许多其他人都面临同样的问题,但这些建议似乎都不起作用。我遵循了this SO 帖子中概述的方法,这与 dotnet/runtime GitHub 上的问题#26449 中的建议相呼应。这是一个重现问题的小型控制台应用程序(针对 .NET Core 3.1):
static void Main(string[] args)
{
var rootCaCertificate = new X509Certificate2("root-ca-cert.cer");
var intermediateCaCertificate = new X509Certificate2("intermediate-ca-cert.cer");
var endUserCertificate = new X509Certificate2("end-user-cert.cer");
var chain = new X509Chain();
chain.ChainPolicy.ExtraStore.Add(rootCaCertificate);
chain.ChainPolicy.ExtraStore.Add(intermediateCaCertificate);
chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority;
chain.ChainPolicy.RevocationMode = X509RevocationMode.Online;
chain.Build(endUserCertificate);
chain.Build(new X509Certificate2(endUserCertificate));
var errors = chain.ChainStatus.ToList();
if (!errors.Any())
{
Console.WriteLine("Certificate is valid");
return;
}
foreach (var error in errors)
{
Console.WriteLine($"{error.Status.ToString()}: {error.StatusInformation}");
}
}
运行时返回三个错误:
UntrustedRoot: A certificate chain processed, but terminated in a root certificate which is not trusted by the trust provider.
RevocationStatusUnknown: The revocation function was unable to check revocation for the certificate.
OfflineRevocation: The revocation function was unable to check revocation because the revocation server was offline.
但是,如果我将根 CA 证书添加到受信任的根 CA 证书存储中,则所有三个错误都会消失。
问题
- 这是我的实现有问题,还是我试图做的事情不可能?
- 我有哪些选择可以尝试实现这一目标?一些谷歌搜索表明 .NET 5 中提供的
X509ChainPolicy.CustomTrustStore可能会节省一天的时间。充气城堡是实现这一目标的另一种选择吗?
【问题讨论】:
-
错误消息的重要部分是“吊销服务器脱机”。检查证书的一种方法是使用证书进行连接。因此,如果您在应用程序中创建服务器并与本地主机建立虚拟连接并且 i 连接完成,那么您就知道证书是好的。错误提示服务器处于离线状态,因此您需要通过创建套接字来创建真正的服务器。
-
嗨@jdweng,感谢您的回复。 CRL 肯定是在线的,因为如果我将根 CA 证书添加到我受信任的根存储中,所有三个错误都会消失。此外,我可以浏览到 CRL 并下载它。
-
我认为你可能会失败,因为 TLS 版本是错误的。尝试将此静态方法添加到代码的开头,这有时会有所帮助:ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;如果 TLS 失败,则连接将失败。
-
@jdweng 抱歉,但您的所有假设和建议都与 OP 问题无关。