为了执行 SSL 证书验证,我将回调分配给
System.Net.ServicePointManager.ServerCertificateValidationCallback
,然后尝试自行构建 X.509 链以检查服务器证书是否由我信任的 CA 集合颁发。
我知道我可以扩展链构建期间要使用的证书集合(通过向
X509Chain.ChainPolicy.ExtraStore
添加新项目) - 但这用于信任不在本地证书存储中的其他证书。
我怎样才能真正限制我自己以编程方式构建的给定商店的连锁店建设?我找不到在调用
X509Store
时使用自定义 X509Chain.Build(X509Certificate2)
对象的方法。
AFAIK,在.NET 中没有办法限制一组可信根(可信锚点)。但是,您可以通过互操作调用本机(类似 C++)CryptoAPI 函数。
基本上,您需要使用 CertCreateCertificateChainEngine 函数并使用自定义输入链接引擎配置结构:CERT_CHAIN_ENGINE_CONFIG。
您将需要创建一个虚拟(无需在 Windows 证书存储中显式注册)存储,添加一组您选择的受信任证书。获取存储句柄/指针并将其传递到
hRestrictedRoot
对象中的 CERT_CHAIN_ENGINE_CONFIG
参数中。在这种情况下,将不会使用默认根存储。该函数返回 HCERTCHAINENGINE
的句柄,然后可以在 CertGetCertificateChain 函数调用(发生实际链验证的地方)中使用。
如果您希望限制(相对于“替换”)信任列表,这非常简单,只需获取回调中提供的链并查看它是否符合要求即可。
HashSet<X509Certificate2> s_allowedRoots = new HashSet<X509Certificate2>
{
trustedCertA,
trustedCertB,
...
};
...
// In your callback
if (errors != SslPolicyErrors.None)
{
return false;
}
X509Certificate2 chainRoot = chain.ChainElements[chain.ChainElements.Count - 1].Certificate;
return s_allowedRoots.Contains(chainRoot);
更新:现在您可以使用 X509chain.ChainPolicy.CustomTrustStore 添加根证书并使用它来构建链。
var chain = new X509Chain();
chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
chain.ChainPolicy.TrustMode = X509ChainTrustMode.CustomRootTrust;
chain.ChainPolicy.CustomTrustStore.Clear();
chain.ChainPolicy.CustomTrustStore.Add(yourRootCertificate);
chain.Build(yourCert);