2011-06-27 107 views
9

我有一個Windows證書頒發機構,用於通過.net/c#發佈客戶端身份驗證證書。我已經能夠成功地通過通過COM調用證書頒發機構的API來以編程方式發佈證書。我在創建客戶端時頒發新證書。如何驗證證書是由特定證書頒發機構創建的?

在運行時,這些客戶端將證書附加到請求到我的服務器。如何以編程方式驗證X509Certificate2是否由我的證書頒發機構的根證書籤名(並拒絕由任何其他源簽名的證書)?

+1

應該是security.se(也許) – Woot4Moo

+2

爲什麼呢?我的問題是如何驗證登錄代碼... –

+0

你有沒有找到一種方法來編碼? – MiguelM

回答

14

我這樣做了很多。這裏有一些簡單的代碼可以使用。

if (!isChainValid)塊中的部分是產生一個相當錯誤的消息。如果你不想要,你不必使用它,但如果鏈不能建立,你應該拋出一個錯誤。鏈元素是檢查你的根的必要條件。

X509Certificate2 authority = GetAuthorityCertificate(); 
X509Certificate2 certificateToValidate = GetCertificateToValidate(); 

X509Chain chain = new X509Chain(); 
chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; 
chain.ChainPolicy.RevocationFlag = X509RevocationFlag.ExcludeRoot; 
chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority; 
chain.ChainPolicy.VerificationTime = DateTime.Now; 
chain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(0, 0, 0); 

// This part is very important. You're adding your known root here. 
// It doesn't have to be in the computer store at all. Neither certificates do. 
chain.ChainPolicy.ExtraStore.Add(authority); 

bool isChainValid = chain.Build(certificateToValidate); 

if (!isChainValid) 
{ 
    string[] errors = chain.ChainStatus 
     .Select(x => String.Format("{0} ({1})", x.StatusInformation.Trim(), x.Status)) 
     .ToArray(); 
    string certificateErrorsString = "Unknown errors."; 

    if (errors != null && errors.Length > 0) 
    { 
     certificateErrorsString = String.Join(", ", errors); 
    } 

    throw new Exception("Trust chain did not complete to the known authority anchor. Errors: " + certificateErrorsString); 
} 

// This piece makes sure it actually matches your known root 
var valid = chain.ChainElements 
    .Cast<X509ChainElement>() 
    .Any(x => x.Certificate.Thumbprint == authority.Thumbprint); 

if (!valid) 
{ 
    throw new Exception("Trust chain did not complete to the known authority anchor. Thumbprints did not match."); 
} 
+0

錯誤將永遠不會爲空;) – HelloWorld

+0

@HelloWorld好吧,如果我今天寫這篇文章的話,我只會使用'if(errors?.Length> 0)'。 :) C#6.很高興知道;我沒有深入研究ToArray()實現,看看如果Select()的IEnumerable沒有返回結果會發生什麼。 –

+0

@ChrisBenard檢查證書是否與您已知的根目錄相匹配的代碼確實沒問題?這段代碼應該匹配做這樣的事情,幾乎總是返回true:'chain.ChainElements.Cast ()。All(x => x.Certificate.Thumbprint!=「XX」);' – Ogglas

0

如果你說你有一個(這是自簽名)證書,那麼你唯一的選擇是保持你的服務器上可用的根證書(當然沒有私鑰),並執行證書驗證程序你的根證書。這是驗證服務器證書鏈的Web客戶端的鏡像情況。

+1

我完全是這種情況。我會澄清我的問題,但我正在尋找驗證c#中籤名所需的特定代碼。 –

+0

@Jeffrey我知道這是如何在我們的SecureBlackbox for .NET中完成的,但不知道如何完成純.NET Framework。 –

+0

可能有更好的方法,但請查看[X509Chain](http://msdn.microsoft.com/zh-cn/library/system.security.cryptography.x509certificates.x509chain.aspx)類。文檔示例顯示的代碼沿着鏈條逐步檢查每個元素。 –

相關問題