问题描述
我已经使用 OpenSSL 生成了一个 CA 和多个证书(由 CA 签名),并且我有一个 .NET/C# 客户端和服务器都使用 SslStream
,每个客户端和服务器都有自己的证书/密钥,相互启用身份验证并禁用撤销.
I've generated a CA and multiple certificates (signed by CA) using OpenSSL and I have a .NET/C# client and server both using SslStream
which each have their own certificates/keys, mutual authentication is enabled and revocation is disabled.
我使用 RemoteCertificateValidationCallback
作为 SslStream
来验证远程服务器的证书,我希望我可以在程序中加载 CA 的公共证书(作为文件)并使用它来验证远程证书,而不是在 Windows 证书存储中实际安装 CA.问题是 X509Chain
不会显示任何其他内容,除非我将 CA 安装到商店中,当我打开其中一个证书的 PEM 版本时,Windows CryptoAPI shell 也不会显示.
I'm using RemoteCertificateValidationCallback
for SslStream
to validate the remote server's certificate and I was hoping I could just load the CA's public certificate (as a file) in the program and use it to verify the remote certificate rather then actually installing the CA in the Windows Certificate Store. The problem is the X509Chain
won't show anything else unless I install the CA into the store, either will the Windows CryptoAPI shell when I open a PEM version of one of the certificates.
我的问题是,当 RemoteCertificateValidationCallback
而不使用 Windows 证书存储或 WCF 来验证证书是否已由我的特定 CA 签名>、X509Certificate
和 X509Chain
似乎没有给我任何可用的东西?
My question is, how can I verify a certificate has been signed by my specific CA just by using the CA's public certificate file without using Windows certificate store or WCF when RemoteCertificateValidationCallback
, X509Certificate
and X509Chain
don't seem to give me anything to work with?
推荐答案
因为 CA 证书不在根证书存储中,您将在 RemoteCertificateValidationCallback() 中看到一个错误标志 SslPolicyErrors.RemoteCertificateChainErrors ;一种可能性是根据您自己的 X509Certificate2Collection 明确验证证书链,因为您没有使用本地存储.
Because the CA certificate is NOT in the root certificate store, you will have within the RemoteCertificateValidationCallback() an error flag of SslPolicyErrors.RemoteCertificateChainErrors ; a possibility is to validate explicitely the certificate chain against your own X509Certificate2Collection, since you are not using the local store.
if (sslPolicyErrors == SslPolicyErrors.RemoteCertificateChainErrors)
{
X509Chain chain0 = new X509Chain();
chain0.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
// add all your extra certificate chain
chain0.ChainPolicy.ExtraStore.Add(new X509Certificate2(PublicResource.my_ca));
chain0.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority;
isValid = chain0.Build((X509Certificate2)certificate);
}
您还可以重用回调中传递的链,在 ExtraStore 集合中添加额外的证书,并使用 AllowUnknownCertificateAuthority 标志进行验证需要,因为您将不受信任的证书添加到链中.
You can also re-use the chain passed in the callback, add your extra certificate(s) in the ExtraStore collection, and validate with the AllowUnknownCertificateAuthority flag which is needed since you add untrusted certificate(s) to the chain.
您还可以通过在受信任的根存储中以编程方式添加 CA 证书来防止原始错误(当然它会打开一个弹出窗口,因为全局添加新的受信任 CA 根是一个主要的安全问题):
You could also prevent the original error by adding programmatically the CA certificate in the trusted root store (of course it opens a popup, for it is a major security problem to globally add a new trusted CA root) :
var store = new X509Store(StoreName.Root, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadWrite);
X509Certificate2 ca_cert = new X509Certificate2(PublicResource.my_ca);
store.Add(ca_cert);
store.Close();
对于那些想用您的 CA 清楚地测试链的人:
For those who want to clearly test the chain with your CA :
另一种可能性是使用库BouncyCastle
来构建证书链并验证信任.选项很清楚,错误也很容易理解.如果成功,它将构建链,否则返回异常.下面的示例:
Another possibility is to use the library BouncyCastle
to build the certificate chain and validate the trust. The options are clear and errors are easy to understand. In cas of success it will build the chain, otherwise an exception is returned. Sample below :
// rootCerts : collection of CA
// currentCertificate : the one you want to test
var builderParams = new PkixBuilderParameters(rootCerts,
new X509CertStoreSelector { Certificate = currentCertificate });
// crls : The certificate revocation list
builderParams.IsRevocationEnabled = crls.Count != 0;
// validationDate : probably "now"
builderParams.Date = new DateTimeObject(validationDate);
// The indermediate certs are items necessary to create the certificate chain
builderParams.AddStore(X509StoreFactory.Create("Certificate/Collection", new X509CollectionStoreParameters(intermediateCerts)));
builderParams.AddStore(X509StoreFactory.Create("CRL/Collection", new X509CollectionStoreParameters(crls)));
try
{
PkixCertPathBuilderResult result = builder.Build(builderParams);
return result.CertPath.Certificates.Cast<X509Certificate>();
...
这篇关于使用 CA 证书文件验证远程服务器 X509Certificate的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!