2011-10-08 204 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庫。 –