2011-10-08 153 views
7

我已经生成使用OpenSSL一个CA和多个证书(由CA签名),我有一个.net/C#客户端和服务器使用SslStream,每个都有自己的证书/密钥,相互身份验证已启用且撤销已禁用。验证远程服务器x509证书使用CA证书文件

我使用RemoteCertificateValidationCallback作为SslStream验证远程服务器的证书,我希望我可以在程序中加载CA的公共证书(作为文件),并用它来验证远程证书,而不是实际安装CA在Windows证书存储区中。问题是X509Chain不会显示任何东西,除非我安装CA进店,要么会在我打开Windows的CryptoAPI外壳的证书之一的PEM版本。

我的问题是,我怎么能验证证书,而无需使用Windows证书存储区或WCF时RemoteCertificateValidationCallbackX509CertificateX509Chain似乎并没有给已经签署了我的特定的CA只使用CA的公钥证书文件我有什么合作?

+1

我不明白为什么将CA证书添加到Windows应用商店导致X509Chain在链中显示它,但如果我不这样做,它不是它的一部分。是否有人在RemoteCertificateValidationCallback内将CA证书添加到链中? – user985122

+0

我仍然无法找到答案:( – user985122

回答

5

因为CA证书不在根证书存储,你将有RemoteCertificateValidationCallback()内的SslPolicyErrors.RemoteCertificateChainErrors的错误标志;一个可能性是明确地验证对自己X509Certificate2Collection证书链,因为你不使用本地存储。

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集合中添加额外的证书(S),并与你既然添加不可信其所需的AllowUnknownCertificateAuthority标志验证连锁证书。

你也可以防止原来的错误由受信任的根存储添加编程CA证书(当然它会打开一个弹出窗口,因为这是一个重大的安全问题在全球范围内增加一个新的受信任的CA根):

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(); 
+0

)另一种可能性是使用'BouncyCastle'库建立证书链并验证信任。选项清晰且错误易于理解。 –

+0

查看回复http ://stackoverflow.com/a/27310276/1038496这里是为了正确检查你自己的CA.上面所做的方法将接受每个CA(没有检查有效性) – Zoka

1

我如何验证证书,但不使用Windows证书存储区或WCF已经签署了我的特定的CA只使用CA的公钥证书文件时RemoteCertificateValidationCallback,x509证书和X509Chain似乎并没有给我任何工作用?

以下代码将避免Windows证书存储和验证链。它与JB的代码有点不同,特别是在使用标志时。下面的代码并不需要AllowUnknownCertificateAuthority(但它确实使用X509RevocationMode.NoCheck,因为我没有CRL)。

功能不要紧的名称。下面,VerifyServerCertificate是相同的回调为RemoteCertificateValidationCallbackSslStream类。您也可以在ServicePointManager中使用ServerCertificateValidationCallback

static bool VerifyServerCertificate(object sender, X509Certificate certificate, 
    X509Chain chain, SslPolicyErrors sslPolicyErrors) 
{ 
    try 
    { 
     String CA_FILE = "ca-cert.der"; 
     X509Certificate2 ca = new X509Certificate2(CA_FILE); 

     X509Chain chain2 = new X509Chain(); 
     chain2.ChainPolicy.ExtraStore.Add(ca); 

     // Check all properties 
     chain2.ChainPolicy.VerificationFlags = X509VerificationFlags.NoFlag; 

     // This setup does not have revocation information 
     chain2.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; 

     // Build the chain 
     chain2.Build(new X509Certificate2(certificate)); 

     // Are there any failures from building the chain? 
     if (chain2.ChainStatus.Length == 0) 
      return true; 

     // If there is a status, verify the status is NoError 
     bool result = chain2.ChainStatus[0].Status == X509ChainStatusFlags.NoError; 
     Debug.Assert(result == true); 

     return result; 
    } 
    catch (Exception ex) 
    { 
     Console.WriteLine(ex); 
    } 

    return false; 
} 

想出如何在默认情况下使用这条产业链(以下chain2),使得没有必要回调。也就是说,将它安装在ssl套接字上,连接将“正常工作”。我有而不是想出了如何安装它,使其传入回调。也就是说,我必须为每个回调调用构建链。我认为这些是.NET中的架构缺陷,但我可能会错过某些明显的东西。

+0

看起来没问题,'chain2'将是证书信任在被测试的证书和根证书之间。现在,如果您对证书执行高级操作,您可能需要使用BouncyCastle库。 –