簡體   English   中英

在 IIS 上托管的 C# 中使用 USB 令牌打開 X509 證書選擇

[英]Open X509 Certificates Selection Using USB Token in C# Hosted on IIS

我正在處理一項要求在 ASP.Net C# 中對 PDF 文件進行數字簽名的要求,並開發了一個應用程序,該應用程序在我的本地機器上使用 USB 令牌獲取客戶端證書。 但是,在 IIS 服務器上托管此應用程序時,出現錯誤“當前會話不是交互式”

任何人都有任何想法,我們如何從 ASP.Net C# 中的客戶端機器獲取 X509Certificates,並且該應用程序托管在 IIS 服務器上而不是控制台應用程序上。

我的代碼供參考:

private void getSign()
{
    X509Store store = new X509Store(StoreLocation.CurrentUser);
    store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
    X509Certificate2 cert = null;
    //manually chose the certificate in the store
    X509Certificate2Collection sel = X509Certificate2UI.SelectFromCollection(store.Certificates, null, null, X509SelectionFlag.SingleSelection);
    if (sel.Count > 0)
        cert = sel[0];
    else
    {
        //MessageBox.Show("Certificate not found");
        return;
    }
    SignWithThisCert(cert);
}

免責聲明:雖然,這不是您問題的直接答案,但可能包含根據業務要求為您提供正確方法的說明。 你的問題有兩個主要問題。 我試圖在評論中討論其中之一,但可能需要解釋。


讓我們嘗試分析您的初始帖子:

任務:讓用戶將 PDF 上傳到 Web 應用程序並對其進行簽名。

要求: PDF 必須使用存儲在客戶端 USB 令牌上的證書進行簽名。

您建議的解決方案:獲取客戶端證書(從客戶端)並在服務器端執行簽名。


讓我們將您的場景中使用的術語和操作形式化。

簽名:文檔簽名用於保證文檔的完整性,確保文檔在簽名后不被以任何方式篡改。 數字簽名提供有關執行簽名的實體的信息。 這增加了不可否認性功能。 一旦簽署,簽署人不得否認簽署事實,並證明文件中的信息在簽署時是正確的。 非對稱簽名需要私鑰。 關聯的公鑰可用於驗證和驗證簽名。

私鑰:是屬於特定客戶端的密鑰對的一部分。 沒有其他人應該知道私鑰。

安全邊界:客戶端(Web 瀏覽器或其他 Web 客戶端)和 Web 服務器運行在不同的安全邊界並且具有不同的信任級別。 他們受不同的行政控制。 結果,Web 服務器對客戶端機器/數據的訪問非常有限,反之亦然:Web 客戶端對服務器機器/數據的訪問非常有限。


您提議的設計假設客戶端選擇文檔並將其上傳到服務器。 然后客戶端選擇一個簽名證書(特別是私鑰)並將其上傳到服務器進行簽名操作。

問題 1:一旦私鑰離開客戶端並被復制到您的 Web 應用程序,您就打破了安全邊界。 結果,密鑰不再是私有的,因為 Web 應用程序擁有私有密鑰的知識,並且它存儲(即使是臨時的)在服務器內存中。 或者,簡單地說,密鑰被泄露和泄露。

客戶不再對其密鑰和由密鑰進行的操作負責。 客戶端可以拒絕使用其私鑰所做的任何事情。 並拒絕您的 Web 應用程序所做的簽名。

問題 2:您提議的設計假定 PDF 已按原樣復制到服務器。 只有這樣它才會被簽署。 然而,一旦文檔(或者它的精確二進制副本,更准確地說)接觸到網絡,客戶端就不再對文檔的准確性負責。 因為文檔在傳輸過程中可能會被轉換,或者某些代碼會在客戶端和文檔簽名代碼之間接觸到文檔。

一旦文檔離開客戶端機器,客戶端就不再負責文檔完整性,因為文檔通過各種代碼段傳遞,將文檔組合成適合傳輸的格式(例如封裝)。 結果,客戶端發送的文檔和服務器端的文檔簽名代碼接收的文檔可能不一樣。 無法保證文檔完整性。 雖然,您可以在傳輸過程中應用 TLS 來保護文檔,但仍有一些地方可以匿名篡改文檔,而沒有人會注意到這一點。

同樣,由於客戶端無法保證 Web 應用程序收到他發送的相同文檔,因此客戶端可以拒絕您嘗試簽署的文檔並拒絕簽名。 因此,使簽名無用,因為它什么也證明不了。

問題 #3:(不是真正的問題,但值得解釋)提供的一段代碼沒有執行預期的任務(即使它看起來在開發環境中工作)。 您的目標是在客戶端調用證書選擇對話框以選擇正確的證書。

在測試期間,您在本地運行所有代碼。 在調試器中,Web 應用程序在當前登錄的用戶(交互式會話)下運行,並且能夠顯示證書選擇對話框。 但是,您無法輕松確定它是在哪個上下文(客戶端或服務器)中執行的,因為客戶端和服務器都運行在同一台機器上並在相同的安全上下文下。 實際上,它是在服務器上下文中調用的。

當您將應用程序部署到 Web 服務器時,您會看到不同之處。 Web 應用程序在某些應用程序池上下文(用戶帳戶)下運行,並且此會話不是交互式的。 結果, X509Certificate2UI類無法顯示對話框,因為沒有人會看到它,也沒有人可以按下按鈕。 無論客戶端和服務器是在相同還是不同的機器上運行,這種行為都是一致的,因為 IIS(或其他 Web 服務器)會立即將關注點和安全邊界分開,而調試器則不會。 客戶端和服務器肯定會在不同的安全上下文下運行。 即使您強制使用相同的上下文,IIS 也會創建輔助非交互式用戶會話來運行 Web 應用程序。

為了在客戶端顯示證書選擇對話框,您必須與客戶端進行深度交互,例如通過 Silverlight(不確定X509Certificate2UI在 Silverlight 中是否可用)或某些 ActiveX 控件。 您必須在客戶端運行一些代碼才能完成此操作。


上述所有內容都顯示了您初始設計中的潛在問題,它們只是違反了基本的安全規則。 技術和工具旨在遵循這些規則,而不是破壞它們。 通過追求您的初始設計,您將被迫不斷與技術斗爭以破壞它們並使您的應用程序非常不安全和易受攻擊。

首選解決方案:我們確定了您設計中的常見風險:客戶端和服務器上的簽名代碼之間的密鑰泄漏和文檔完整性。 為了輕松緩解這一切,您應該做的唯一一件事是:在客戶端執行文檔簽名。 通過這樣做,簽名私鑰永遠不會從客戶端泄漏,並且在 Web 應用程序簽名和接收的過程中將保證文檔的完整性。

現在,我們可以談談證書屬性。 您的要求是使用存儲在 USB 令牌上的證書。 我不知道你在這里指的是哪種令牌。 是帶有PFX的標准USB大容量存儲設備,或者是加密設備(帶有USB接口的智能卡,通常稱為USB令牌。例如,Aladdin(SafeNet)eToken設備)。

如果是 USB 大容量存儲設備,則它不能成為要求的一部分,因為通用 USB 驅動器不提供任何有助於識別證書來源的信息。 任何證書都可以輕松復制到 USB 驅動器,任何證書都可以從 USB 驅動器復制。

如果是 USB 智能卡,則有一種方法可以識別證書是來自該設備還是其他來源。 智能卡有一個獨特的屬性:私鑰永遠不會離開卡。 所有操作都在卡上執行(這就是為什么它們比存儲在 PC 上的證書慢的原因)。

這通常是通過在證書頒發期間向簽名證書添加額外信息來實現的。 例如,通過添加Certificate Policies證書擴展。 這將要求 CA 運營商/經理確保具有指定證書策略的證書僅部署到智能卡。

如果建立了這些過程,您就可以使用服務器端的代碼來接受簽名的 PDF 文檔並檢查簽名證書的內容。 例如,您閱讀證書策略並希望在那里看到特定條目。 如果它出現,那么您可以安全地假設文檔是使用存儲在智能卡上的證書簽名的,因為密鑰不能從卡設備復制到任何地方。 如果證書不包含證書策略中的特定條目,那么您可以拒絕文檔接受並要求客戶端使用正確的證書。

USB令牌在其驅動程序上方具有CSP(加密服務提供程序)層。 這增加了一項功能:在插入令牌時,令牌中的證書在證書存儲中變為可用,並且可以使用CSP通過相應證書中的句柄訪問令牌中的私鑰。

對於在瀏覽器中使用Web應用程序中的令牌執行不同任務,請參考以下答案:

簽署PDF: https//stackoverflow.com/a/55676351/9659885

對於身份驗證: https//stackoverflow.com/a/55757349/9659885

簽名內容: https//stackoverflow.com/a/55692742/9659885

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM