在IIS上托管的C#中使用USB令牌打开X509证书选择

在IIS上托管的C#中使用USB令牌打开X509证书选择,c#,iis,itext,digital-signature,x509certificate,C#,Iis,Itext,Digital Signature,X509certificate,我正在进行一项要求,要求在ASP.NETC#中对PDF文件进行数字签名,并开发了一个应用程序,该应用程序在我的本地计算机上使用USB令牌获取客户端证书。但是,在IIS服务器上托管此应用程序时,出现错误“当前会话不是交互式的” 任何人都知道,我们如何从ASP.NETC#中的客户端计算机获取X509Certificates,而这个应用程序托管在IIS服务器上,而不是控制台应用程序 我的参考代码: private void getSign() { X509Store store = new X

我正在进行一项要求,要求在ASP.NETC#中对PDF文件进行数字签名,并开发了一个应用程序,该应用程序在我的本地计算机上使用USB令牌获取客户端证书。但是,在IIS服务器上托管此应用程序时,出现错误“当前会话不是交互式的”

任何人都知道,我们如何从ASP.NETC#中的客户端计算机获取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应用程序并进行签名

要求:必须使用存储在客户端USB令牌上的证书对PDF进行签名

您建议的解决方案:获取客户端证书(从客户端)并在服务器端执行签名。
让我们将场景中使用的术语和操作形式化

签名:文档签名用于保证文档的完整性,并确保文档在签名后未被任何方式篡改。数字签名提供有关执行签名的实体的信息。这增加了不可抵赖特性。一旦签字,签字人就不能否认签字事实并证明文件中的信息在签字时是正确的。非对称签名需要私钥。关联的公钥可用于验证签名

私钥:是属于特定客户端的密钥对的一部分。其他人不应该知道私钥

安全边界:客户端(web浏览器或其他web客户端)和web服务器在不同的安全边界中运行,并具有不同的信任级别。它们受到不同的行政控制。因此,web服务器对客户端机器/数据的访问非常有限,反之亦然:web客户端对服务器机器/数据的访问非常有限。
您建议的设计假定客户端选择文档并将其上载到服务器。然后,客户端选择一个签名证书(特别是私钥),并将其上载到服务器进行签名操作

问题#1:一旦私钥离开客户端并复制到您的web应用程序,您就突破了安全边界。因此,密钥不再是私有的,因为web应用程序拥有私有密钥的知识,并且它被存储(即使是暂时的)在服务器内存中。或者,简单地说,密钥被泄露和泄露

客户不再对其密钥和密钥所做的操作负责。客户端可以拒绝使用其私钥进行的任何操作。并拒绝您的web应用程序所做的签名

问题#2:您提出的设计假设PDF按原样复制到服务器。然后才签字。然而,一旦文档(或者更准确地说是其精确的二进制副本)接触到网络,客户端就不再对文档的准确性负责。因为文档可能在传输过程中被转换,或者某些代码在客户端和文档签名代码之间接触文档

一旦文档离开客户机,客户机就不再负责文档的完整性,因为文档将通过组成文档的各种代码段传递到适合传输的格式(例如封装)。因此,客户端发送的文档和服务器端的文档签名代码接收的文档可能不同。文档完整性无法保证。尽管您可以在传输过程中应用TLS来保护文档,但仍有一些地方可以匿名篡改文档,没有人会注意到这一点

同样,由于客户端不能保证web应用程序收到了他发送的相同文档,客户端可以拒绝您尝试签名的文档并拒绝签名。因此,使签名无效,因为它证明不了什么

问题#3:(不是真正的问题,但值得解释)提供的代码段不执行预期任务(即使它看起来在开发环境中工作)。您的目标是调用客户端上的证书选择对话框来选择合适的证书

在测试期间,您将在本地运行所有代码。在调试器中,web应用程序在当前登录的用户(即交互式会话)下运行,并且能够显示证书选择对话框。但是,您无法轻松确定在哪个上下文(客户机或服务器)中执行它,因为客户机和服务器都运行在同一台机器上,并且在同一安全上下文下。实际上,它是在服务器上下文下调用的

当您将应用程序部署到web服务器时,您会看到不同之处。Web应用程序在某些应用程序池上下文(用户帐户)下运行,并且此会话不是交互式的。因此,
X509Certificate2UI
class无法显示该对话框,因为没有人会看到它,也没有人可以按下它上的按钮。无论客户端和服务器运行在相同或不同的计算机上,此行为都是一致的,因为IIS(或其他web服务器)会立即分离关注点和安全边界,而调试器不会。客户端和服务器肯定会在不同的安全环境下运行。即使您强制使用相同的上下文,IIS也会创建一个辅助的非交互式用户会话来运行web应用程序

为了在客户端上显示证书选择对话框,您必须与客户端进行深入的交互,例如,通过Silverlight(不确定
X509Certificate2UI
是否可用)