2016-06-16 101 views
1

我必須在非瀏覽器應用程序中驗證應在IOS,Android和Linux上運行的HttpRequestswebsocket連接的幾個SSL證書。 當通過HTTPS發生連接時,我收到一個X509Certificate2對象數組,其中最底層的是服務器證書,最頂層的是根CA(希望)。作爲一個例子,當我連接到https://google.com我接收3 X509Certificate2具有以下SubjectName.Name如何在Mono和多個平臺上使用X509Certificate2正確驗證SSL證書

  • 0:"CN=google.com, O=Google Inc, L=Mountain View, S=California, C=US"
  • 1:"CN=Google Internet Authority G2, O=Google Inc, C=US"
  • 2:"CN=GeoTrust Global CA, O=GeoTrust Inc., C=US"

我現在需要驗證具有給定信息的證書驗證和以下驗證:

  • 鏈方面的信任驗證
  • 主機名驗證
  • 證書撤銷驗證

我試過和不被理解和失敗:

當我調用X509Certificate2.Verify()方法對每個證書它每次都獨立返回false。我也不明白爲什麼它可以返回任何其他東西,然後false因爲驗證獨立發生。相反,只要我理解了理論,就應該檢查完整的鏈,即所有證書。

然後我用了X509Chain類:

foreach (X509Certificate2 cert in allthreecerts) 
    { 
     X509Chain chain = new X509Chain(); 
     X509ChainPolicy chainPolicy = new X509ChainPolicy() 
     { 
      RevocationMode = X509RevocationMode.Offline, 
      RevocationFlag = X509RevocationFlag.EntireChain 
     }; 
     chain.ChainPolicy = chainPolicy; 
     if (!chain.Build(cert)) 
     { 
      foreach (X509ChainElement chainElement in chain.ChainElements) 
      { 
       foreach (X509ChainStatus chainStatus in chainElement.ChainElementStatus) 
       { 
        Debug.WriteLine(chainStatus.StatusInformation); 
       } 
      } 
     } 
    }    

此打印出RevocationStatusUnknownOfflineRevocation爲每個證書。

再一次,我不明白爲什麼這應該工作,因爲一個鏈獨立建立每個證書。不應該將父證書作爲子證書頒發給所有根CA?

我認爲我需要某種方式,但不知道如何。

爲了驗證證書吊銷,所有客戶端都需要提供證書吊銷列表。我在哪裏可以得到這樣的清單,並在哪裏加載它並告訴鏈條使用這個本地清單?

同樣的問題是信任鏈驗證,因爲上次認證應該是根認證,並且必須是客戶端可信根CA之一。因此,我必須加載,例如,隨Firefox附帶的所有根CA,並檢查根CA是否是其中之一?什麼是最好的方式來做到這一點?

[更新] 我在google.com示例中複製粘貼錯誤,我粘貼了兩個相同的證書主題名稱。

+0

'RevocationMode = X509RevocationMode.Offline' - 將其切換爲'Online'。客戶端必須具有本地CRL/OCSP高速緩存才能在脫機模式下成功驗證撤銷。 – Crypt32

+0

那麼這就是關鍵。我正在實施「客戶」。那麼如何提供這樣的CRL。這是我問的問題。 – zlZimon

+1

CRL從在線資源中檢索。 CRL位置在CRL分發點證書擴展中指定。或者在「管理信息訪問」擴展中的「在線證書狀態協議」部分。 – Crypt32

回答

1

When a connection via HTTPS happens I receive an array of X509Certificate2 objects where the bottom one is the server certificate and the most top one the root CA (hopefully).

如果您確實從SSL服務器獲得了root ca證書,那麼SSL服務器配置不正確。它應該返回其服務器證書和整個鏈路,除了根CA證書。

When I call the X509Certificate2.Verify() method on each certificate independently it returns false everytime.

正如X509Certificate2.Verify方法documentation表示This method builds a simple chain for the certificate and applies the base policy to that chain.現在是什麼the base policy我不知道。但ChainPolicy的默認值是RevocationMode = X509RevocationMode.Online。至於單聲道,這種方法的來源可以找到here。 X509Chain的單聲道實現源可以在here找到。

​​

還有什麼要當你指定RevocationMode = X509RevocationMode.Offline它打印,並有在高速緩存(可能)沒有的CRL或OCSP響應?

In order to verify the certificate revocation all clients need to provide a certificate revocation list. Where do I get such a list and where to I load it and tell the chain to use this local list?

鏈中的每個證書(除了根CA證書)都包含到CRL的鏈接(或多個鏈接)。 .NET和最有可能的Mono has一個將在證書中找到CRL鏈接的實現,將下載它並檢查證書是否未被吊銷。

The same problem is the Chain-of-trust verification since the last certification should be a root certification and must be one of the clients trusted root CA's. So I have to load, for example, all root CA which are shipped with Firefox and check if the root CA is one of them? What is the best way to do that?

不,RevocationFlag = X509RevocationFlag.EntireChain會使用一些商店,單聲道用途爲你做的。我不知道它是否是Firefox商店,但在Linux上它有自己的商店,您可以從Firefox商店導入根CA證書。檢查ChainElements並親自查看它找到的證書。

我建議你用RevocationMode = X509RevocationMode.OnlineRevocationFlag = X509RevocationFlag.EntireChain建立只有SSL服務器證書的鏈(因爲這將檢查鏈中向上的所有證書)。我還會嘗試將X509Chain的ExtraStore屬性設置爲您從SSL服務器獲取的證書列表。在構建方法之後,我將讀取屬於狀態數組的X509Chain對象的ChainStatus屬性。我會選擇所有未將X509ChainStatus.Status設置爲NoError的狀態。如果有任何這樣的狀態,我會拋出並記錄每個X509ChainStatus.Status和X509ChainStatus.StatusInformation

HTH

+0

這是我不明白的部分。如果這只是鏈中的一個證書,那麼X509Certificate2.Verify'如何構建一個完整的鏈?我設置了'RevocationMode = X509RevocationMode.Online',它產生完全相同的結果。 'ExtraStore'屬性有一個私人二傳手,所以我不能設置它。但是,如果CRL下載/檢查,並且如果使用CA存儲,那麼它不應該已經工作(當使用'RevocationMode = X509RevocationMode.Online'時)? – zlZimon

+0

X509Chain的ChainStatus屬性始終包含3個元素。 「PartialChain」,「RevocationStatusUnknown」和「OfflineRevocation」即使使用'RevocationMode = X509RevocationMode.Online' – zlZimon

+1

@zlZimon'X509Certificate2.Verify'使用一些Mono證書存儲來查找證書來構建鏈。 SSL服務器確實(不應該)發送根CA證書,因此客戶必須針對您擁有受信任根CA證書的證書存儲區構建鏈。嘗試從[本網站](http://www.mono-project.com/docs/faq/security/)tlstest。同樣在這個頁面上,你會發現'注意Mono的默認安裝不會信任任何人!'所以你需要使用'certmgr.exe'或'mozroots.exe'來手動填寫受信任的根證書。 – pepo