如何使用 C# 检测证书链不完整的证书?C# dotnet 核心说它们是有效的而不是无效的



我正试图编写一些代码来验证网站的证书是否有效(例如incompletechain.badssl.com)。我遇到的这个问题是,在证书验证期间,窗口(或dotnet框架)似乎过于有用,甚至可以修复链。当链到达我的验证证书回调函数时,链与主机服务器不同,并且是有效的。有没有人知道一种方法来绕过似乎是cryptoapi的链固定功能,只是使用证书"是"?验证链?

我已经尝试了httpclient和sslstream的验证证书回调。两者都表示链是有效的,而不是无效的。

例如,如果证书链无效,curl请求会失败,因为我希望我的请求失败。

curl get https://incomplete-chain.badssl.com
% Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
Dload  Upload   Total   Spent    Left  Speed
0     0    0     0    0     0      0      0 --:--:--  0:00:02 --:--:--     0
curl: (6) Could not resolve host: get
% Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
Dload  Upload   Total   Spent    Left  Speed
0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
curl: (60) SSL certificate problem: unable to get local issuer certificate
More details here: https://curl.se/docs/sslcerts.html
curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.

openssl还正确地将这些不完整的链显示为无效

$ openssl s_client -showcerts -connect incomplete-chain.badssl.com:443
CONNECTED(00000188)
---
Certificate chain
0 s:C = US, ST = California, L = Walnut Creek, O = Lucas Garron Torres, CN = *.badssl.com
i:C = US, O = DigiCert Inc, CN = DigiCert SHA2 Secure Server CA
-----BEGIN CERTIFICATE-----
the certificate 
-----END CERTIFICATE-----
---
Server certificate
subject=C = US, ST = California, L = Walnut Creek, O = Lucas Garron Torres, CN = *.badssl.com
issuer=C = US, O = DigiCert Inc, CN = DigiCert SHA2 Secure Server CA
---
No client certificate CA names sent
Peer signing digest: SHA512
Peer signature type: RSA
Server Temp Key: ECDH, P-256, 256 bits
---
SSL handshake has read 2414 bytes and written 455 bytes
Verification error: unable to verify the first certificate
---

编辑:这是一个尝试使用WebRequest (https://dotnetfiddle.net/2aybuI)

using System;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
public class Program
{
public static void Main(string[] args)
{
var request = (HttpWebRequest)WebRequest.Create("https://incomplete-chain.badssl.com");
request.AllowAutoRedirect = false;
request.ServerCertificateValidationCallback = ServerCertificateValidationCallback;
var response = (HttpWebResponse)request.GetResponse();
response.Close();
}
private static bool ServerCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
if (sslPolicyErrors != SslPolicyErrors.None)
{
return false;
}
var newChain = new X509Chain();
newChain.ChainPolicy.DisableCertificateDownloads = true;
// Skip the leaf cert and stop short of the root cert.      
X509ChainElementCollection chainElements = chain.ChainElements;
for (int i = 1; i < chainElements.Count - 1; i++)
{
newChain.ChainPolicy.ExtraStore.Add(chainElements[i].Certificate);
}
var result = newChain.Build(chainElements[0].Certificate);
// This is True and I want it to be False
Console.WriteLine($"This is {result} and I want it to be False");
return result;
}
}

这里有两个老问题,似乎有类似的问题,但没有解决方案。

  1. 不完整链SSL证书,通过。net Core 2.2验证

  2. X509Chain.Build()方法对无效证书返回true

如果你使用的是。net 5+,你可以设置chain.ChainPolicy.DisableCertificateDownloads = true来阻止它使用AIA记录来重建链。请注意,这不会绕过从本地缓存解析内容,因此,如果中间已经缓存,您仍然会得到一个完整构建的链。

没有办法在SslStream构建的链上获得该集来验证远程证书,并且构建链的SslStream可能会导致底层系统缓存中间(因为它必须下载它,并且它链接到一个受信任的根,所以它值得缓存)。

相关内容