2016-12-09 84 views
0

使用框架4.5.1和下面的要求,我做對了嗎?c#驗證X509Certificate2:我是否正確地執行此操作?

  1. 證書中的URL必須與給定的URL
  2. 證書必須是有效的和值得信賴的
  3. 該證書必須未到期

以下傳球配合,但是這足夠了嗎?

特別是打電話給chain.Build(cert)滿足#2以上?

protected bool ValidateDigitalSignature(Uri uri) 
    { 
     bool isValid = false; 
     X509Certificate2 cert = null; 
     HttpWebRequest request = WebRequest.Create(uri) as HttpWebRequest; 
     using (HttpWebResponse response = request.GetResponse() as HttpWebResponse) 
     { 
      response.Close(); 
     } 

     isValid = (request.ServicePoint.Certificate != null); 
     if(isValid) 
      cert = new X509Certificate2(request.ServicePoint.Certificate); 
     if (isValid) 
     { 
      X509Chain chain = new X509Chain(); 
      chain.ChainPolicy.RevocationMode = X509RevocationMode.Online; 
      chain.ChainPolicy.RevocationFlag = X509RevocationFlag.EntireChain; 
      chain.Build(cert); 
      isValid = (chain.ChainStatus.Length == 0); 
     } 
     if (isValid) 
     { 
      var dnsName = cert.GetNameInfo(X509NameType.DnsName, false); 

      isValid = (Uri.CheckHostName(dnsName) == UriHostNameType.Dns 
       && uri.Host.Equals(dnsName, StringComparison.InvariantCultureIgnoreCase)); 
     } 
     if (isValid) 
     { 
      //The certificate must not be expired 
      DateTimeOffset today = DateTimeOffset.Now; 
      isValid = (today >= cert.NotBefore && today <= cert.NotAfter); 
     } 
     return isValid; 
    } 

回答

1

如果您試圖驗證HTTPS證書是否有效,HttpWebRequest可以爲您做到這一點。

爲了使HttpWebRequest的檢查,你需要調用GetResponse()之前設置的全局ServicePointManager.CheckCertificateRevocationList = true撤銷狀態(我認爲這是GetResponse的,而不是調用創建())。

這將隨後檢查:

  • 證書鏈接到受信任的根
  • 證書沒有過期(和其他類似的東西)
  • 請求主機名匹配,它應該

這是你詢問的三點。最難的是讓主機名匹配正確,因爲

  1. 可以有幾個SubjectAlternativeName DNS條目,並沒有一個好方法在.NET中詢問它們。
  2. 任何SubjectAlternativeName DNS條目允許在其中包含通配符(*)。但是,主題CN值不是(並且.NET API不會指出您返回的是哪種類型的名稱)。
  3. IDNA等名稱規範化。

實際上,HttpWebRequest不會自動爲您做的事情(除非您設置全局),那就是檢查撤銷。你可以做到這一點通過

HttpWebRequest request = WebRequest.Create(uri) as HttpWebRequest; 
request.ServerCertificateValidationCallback = ValidationCallback; 

private static bool ValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) 
{ 
    // Since you want to be more strict than the default, reject it if anything went wrong. 
    if (sslPolicyErrors != SslPolicyErrors.None) 
    { 
     return false; 
    } 

    // If the chain didn't suppress any type of error, and revocation 
    // was checked, then it's okay. 
    if (chain.ChainPolicy.VerificationFlags == X509VerificationFlags.None && 
     chain.ChainPolicy.RevocationMode == X509RevocationMode.Online) 
    { 
     return true; 
    } 

    X509Chain newChain = new X509Chain(); 
    // change any other ChainPolicy options you want. 
    X509ChainElementCollection chainElements = chain.ChainElements; 

    // Skip the leaf cert and stop short of the root cert. 
    for (int i = 1; i < chainElements.Count - 1; i++) 
    { 
     newChain.ChainPolicy.ExtraStore.Add(chainElements[i].Certificate); 
    } 

    // Use chainElements[0].Certificate since it's the right cert already 
    // in X509Certificate2 form, preventing a cast or the sometimes-dangerous 
    // X509Certificate2(X509Certificate) constructor. 
    // If the chain build successfully it matches all our policy requests, 
    // if it fails, it either failed to build (which is unlikely, since we already had one) 
    // or it failed policy (like it's revoked).   
    return newChain.Build(chainElements[0].Certificate); 
} 

而且,值得注意的,因爲我把示例代碼在這裏,你只需要檢查chain.Build()的返回值,因爲如果任何證書,這將是錯誤的已過期或不適用。您也可能需要檢查構建鏈中的根證書(或中間數據庫,或其他),作爲期望值(證書固定)。

如果ServerCertificateValidationCallback返回false,則會在GetResponse()上引發異常。

你應該嘗試的驗證出來,以確保它的工作原理:

+0

感謝真正幫助 – kevcoder

相關問題