我正在尝试编写一些代码来验证网站的证书是否有效(例如,不完整的链.badssl.com)。我遇到的这个问题是,在证书验证期间,windows(或 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;
}
}
这是两个似乎有类似问题但没有解决方案的老问题。