2013-10-06 183 views
1

大家,我想写一些关于SSL和这里的问题:SslStream认证失败

我已经建立了下面的事情:

  • CA证书(自制CA)
  • 服务器PFX,服务器证书,服务器密钥(由自制CA为“localhost”签署)

现在我使用的.Net SslStream来测试连接:(客户端和服务器都在不同的线程,和TCP连接离子已建成)

客户:

sslStream.AuthenticateAsClient("localhost"); 

服务器:

sslStream.AuthenticateAsServer(serverCert); 
//serverCert is X509Certificate2 built from "server.pfx" 

客户的AuthenticateAsClient方法将抛出一个异常

“根据验证过程的远程证书无效“。

我想是因为服务器的证书是由不可信的CA签名的,所以身份验证失败了,那我该如何将CA证书添加到我的信任列表中呢?

我尝试添加下面的客户端代码的代码,但它不会工作

 X509Store store = new X509Store(StoreName.TrustedPublisher, StoreLocation.CurrentUser); 
     store.Open(OpenFlags.ReadWrite); 
     store.Add(new X509Certificate2(Resources.CACertPath)); 
     store.Close(); 
     sslStream.AuthenticateAsClient("localhost"); 
+0

一种方法是完全丢弃CA并编写验证回调函数,将证书指纹与硬编码值进行比较。 – CodesInChaos

+0

@CodesInChaos是的,我可以实现RemoteCertificateCallback并设法返回true,但这种方法是有限的,因为如果我们想要信任一个新的证书,我必须修改代码。我想知道是否有一种方法可以在C#代码中加载CA证书? – Jerrylk

回答

0

下面的代码将避免在Windows证书存储和验证链。

我看不出有什么理由将验证链的CA证书添加到证书库中的数百个。这意味着Windows将尝试使用“数百+ 1”证书来验证链,而不是真正需要的证书。

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

该函数的名称无关紧要。下面,VerifyServerCertificateSslStream类中的RemoteCertificateValidationCallback是相同的回调。您也可以在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; 
}