Dot-Net

.NET 應用程序無法發送客戶端證書 - Win 7 與 Win XP?

  • March 25, 2012

我正在開發一個使用 HttpWebRequest 向另一台伺服器發送請求的 ASP.NET Web 應用程序。它通過 HTTPS 發送請求,遠端伺服器需要客戶端證書。.NET 應用程序中的請求失敗,顯然無法發送正確的客戶端證書。如果我只需使用網路瀏覽器(特別是 Chrome)訪問 url,就能夠成功連接並發送客戶端證書。

下面的程式碼是一個簡單的複制,只有一個基本的 GET 請求。

var r = WebRequest.Create(url) as HttpWebRequest;
r.ClientCertificates = new X509CertificateCollection { myX509Cert };
using (var resp = r.GetResponse() as HttpWebResponse) {
   ...
}

我得到了我們最喜歡的例外,“無法創建 SSL/TLS 安全通道”。通常,這些類型的問題指向證書私鑰的權限問題。我嘗試了我能想到的一切來確保這一切都正確配置,但也許我錯過了一些東西。長話短說,遠端伺服器正在發送一個CertificateRequest帶有列表的 TLS,該列表似乎可以正確辨識我的客戶端證書,但我的應用程序無法響應任何客戶端證書。

這是我的設置:

  • Windows 7 專業版 64 位
  • 能夠在 Visual Studio 開發伺服器中執行的 ASP.NET MVC 3/.NET 4 應用程序、在本地 IIS 中執行的 ASP.NET WebForms/.NET 3.5 應用程序以及 .NET 控制台應用程序/.NET 4 中重現該問題
  • 最近安裝了 Microsoft .NET Framework 4.5。尚未檢查這是否可能是一個問題

這是我嘗試過的所有內容,以及我所知道的:

  • 此程式碼在 Windows XP 機器上執行時似乎執行良好
  • 我確保將我的客戶端證書導入到本地電腦、個人證書儲存中,並為我自己和所有相關 IIS 使用者正確配置了私鑰權限
  • 我嘗試在我的機器上重新安裝證書幾次
  • 我已確認 .NET 應用程序可以訪問 X509 證書並且HasPrivateKey= true
  • 確保我的客戶證書有效。它實際上是執行此應用程序的 Web 伺服器的 SSL 證書
  • PreAuthenticate = true在請求對像中設置。沒有改變
  • 我試過設置ServicePointManager.Expect100Continue = false,沒有任何區別
  • 我嘗試設置ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3,但顯然遠端伺服器需要 TLS,所以這沒有幫助
  • 我將ServicePointManager.ServerCertificateValidationCallback委託設置為始終返回 true。但是請求在 TLS 握手的早期就失敗了,甚至在它呼叫這個委託之前
  • 當我在 Chrome 中訪問 URL 時,它要求我提供客戶端證書,提供正確的客戶端證書作為選項,我選擇該證書並得到有效響應。當我在 Fiddler 中建構請求時也可以正常工作。因此,這絕對是我的 .NET 程式碼的具體問題,而不是證書本身或遠端伺服器等。
  • 我正在使用的供應商在不同的遠端伺服器上設置了相同的服務,並且該服務需要不同的客戶端證書。所以我用不同的 URL 和客戶端證書嘗試了同樣的事情並得到了同樣的失敗

我添加了System.Net 跟踪並看到了這個:

SecureChannel#26717201 - 我們有使用者提供的證書。伺服器已指定 6 個頒發者。尋找與任何頒發者匹配的證書。

SecureChannel#26717201 - 剩下 0 個客戶端證書可供選擇。

InitializeSecurityContext(緩衝區內計數=2,緩衝區外長度=0,返回程式碼=CertUnknown)。

我啟用了完整的SCHANNEL 日誌記錄,並看到了這個警告:

遠端伺服器已請求 SSL 客戶端身份驗證,但找不到合適的客戶端證書。將嘗試匿名連接。此 SSL 連接請求可能成功或失敗,具體取決於伺服器的策略設置。

我執行了 Wireshark,看到遠端伺服器發送了一個CertificateRequest,它似乎有一個Distinguished Name條目,其中包含精確指定的客戶端證書的 CN\OU\O 值。之後,我的應用程序發送一個沒有證書的證書響應。

似乎我在設置此證書以在 Windows 7 中與 .NET 應用程序一起正常工作時遺漏了一些東西。我最好的猜測是,與 XP 機器相比,我的新 Windows 7 機器上有一些不同的東西,這導致了這種情況現在失敗。我目前無法訪問 Windows XP 環境來確認這一點;我會在幾天內解決這個問題,但我真的很想盡快解決這個問題。

任何想法將不勝感激。謝謝!

編輯如上所述,當連接到 Chrome 中的 URL 時,瀏覽器要求我提供客戶端證書,我可以提供正確的證書並成功連接。但是,我無法在 Internet Explorer (9) 中成功執行此操作。我只是得到“Internet Explorer 無法顯示網頁”,沒有其他提示或解釋。有人告訴我,這可能WebRequest.Create與 IE 類似的行為有關。我正在研究這可能意味著什麼,但會重視對此的任何想法。

編輯另外,我應該注意遠端伺服器使用自簽名 SSL 證書。我最初認為這可能是問題所在,因此我將證書添加為 MMC 中的受信任根,以便證書在我的機器上顯示為有效。這並沒有解決問題。

結果證明這是一個相當簡單的問題,但很難發現。我的應用程序的遠端伺服器在其密鑰庫中有我的客戶端證書,但在我的客戶端證書的信任鏈中沒有任何根證書。

我能夠使用我的程式碼成功地將請求發送到需要客戶端證書的不同伺服器。我在發送此成功請求時在 Wireshark 中進行了擷取,並且在將失敗的請求發送到另一台伺服器時也進行了擷取。在 Wireshark 擷取中,我找到了“Server Hello”並比較了從遠端伺服器發送的消息。“好的”遠端伺服器正在發送我的客戶端證書以及消息的“證書請求”部分中的根證書。“壞”的遠端伺服器只發送我的客戶端證書。

這提醒我 System.Net 診斷跟踪讀取“伺服器已指定 6 個頒發者……留下 0 個客戶端證書可供選擇”。所以事實證明,“發行人”是這裡的關鍵術語。最初很容易忽略,因為在我對 TLS 握手的初步分析中,伺服器在證書請求中發送了我的客戶端證書。事後看來,伺服器應該發送您的根證書而不是您的客戶端證書本身是有道理的。

引用自:https://stackoverflow.com/questions/9858275