C# 用户在使用数字签名的应用程序中取消了该操作

C# 用户在使用数字签名的应用程序中取消了该操作,c#,certificate,private-key,C#,Certificate,Private Key,web应用程序的思想是使用从智能卡加载的数字签名对文档进行签名 它被发布并设置为在本地用户机器上工作。为此,我正在使用IIS来设置绑定,并启用接受客户端证书 它与托管在云上的web应用程序通信 我正在从智能卡和私钥成功获取证书 我使用私钥对文档进行签名 private InvoiceResult SignDocument(XmlDocument doc) { InvoiceResult resultValue; try {

web应用程序
的思想是使用从
智能卡
加载的
数字签名
对文档进行签名

它被发布并设置为在
本地用户
机器上工作。为此,我正在使用
IIS
来设置
绑定
,并启用接受
客户端证书

它与托管在
云上的
web应用程序
通信

我正在从
智能卡
私钥
成功获取
证书

我使用
私钥
对文档进行签名

 private InvoiceResult SignDocument(XmlDocument doc)
    {
        InvoiceResult resultValue;

        try
        {
            var (resultValue2, certificate) = GetDefaultCertificateStoredOnTheCard();
            resultValue = resultValue2;
            SignXmlDocumentWithCertificate(doc, certificate);

            resultValue = InvoiceResult.Success;
        }
        catch (Exception ex)
        {
            _log.TraceInformation($"Error when compute signature and it is : {ex.Message}");
            _log.TraceInformation($"Additional info => stack trace : {ex.StackTrace}");

            resultValue = InvoiceResult.CannotSignXmlFiles;
        }
        return resultValue;
    }


 public (InvoiceResult resultValue, X509Certificate2 cert) GetDefaultCertificateStoredOnTheCard()
    {

        var resultValue = InvoiceResult.Success;

        using X509Store x509Store = new X509Store(StoreName.My, StoreLocation.CurrentUser);

        X509Store store = x509Store;
        store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);

        X509Certificate2Collection certs = store.Certificates.Find(X509FindType.FindByTimeValid, DateTime.Now, true);

        certs = certs.Find(X509FindType.FindByThumbprint, Settings.Default.Thumbprint, true);


        if (certs.Count == 0)
        {
            resultValue = InvoiceResult.CannotFindSignature;
        }
        X509Certificate2 cert = certs[0];
        if (cert.HasPrivateKey)
        {
            // software cert
            _ = cert.PrivateKey as RSACryptoServiceProvider;

        }
        else
        {
            // certificate from smartcard
            CspParameters csp = new CspParameters(1, "Microsoft Base Smart Card Crypto Provider")
            {
                Flags = CspProviderFlags.UseDefaultKeyContainer
            };
            _ = new RSACryptoServiceProvider(csp);
        }


        return (resultValue, cert);
    }

    private InvoiceResult SignXmlDocumentWithCertificate(XmlDocument xmlDoc, X509Certificate2 cert)
    {
        InvoiceResult resultValue = InvoiceResult.Success;

        SignedXml signedXml = new SignedXml(xmlDoc)
        {
            //we will sign it with private key
            SigningKey = cert.PrivateKey
        };

        if (cert.PrivateKey == null)
        {
            resultValue = InvoiceResult.CannotSignXmlFiles;

            //   throw new ArgumentException("Please make sure the application for electronic signatures is installed, so the private key can be obtained from the smart card!");
        }


        Reference reference = new Reference
        {
            //sign the entire doc
            Uri = ""
        };
        XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
        reference.AddTransform(env);
        signedXml.AddReference(reference);

        //PublicKey part
        RSACryptoServiceProvider rsaprovider = (RSACryptoServiceProvider)cert.PublicKey.Key;
        RSAKeyValue rkv = new RSAKeyValue(rsaprovider);

        KeyInfo keyInfo = new KeyInfo();
        keyInfo.AddClause(new KeyInfoX509Data(cert));
        //We add the public key here
        keyInfo.AddClause(rkv);

        signedXml.KeyInfo = keyInfo;
        _log.TraceInformation($"Cert has private key or not? {cert.HasPrivateKey}");

        signedXml.ComputeSignature();

        // Get the XML representation of the signature and save
        // it to an XmlElement object.
        _log.TraceInformation($"It computes the signature succesfully");

        XmlElement xmlDigitalSignature = signedXml.GetXml();

        // Append the element to the XML document.
        xmlDoc.DocumentElement.AppendChild(xmlDoc.ImportNode(xmlDigitalSignature, true));

        _log.TraceInformation($"It appends the signature succesfully");


        return resultValue;
    }
它在
Release/Debug
上可以正常工作,但在
Publish
中不能正常工作。它会弹出一个
弹出窗口
,要求输入一个
PIN
,一旦输入了
PIN
,文档就会被签名

它到达
signedxml.ComputeSignature
并返回一个错误:

该操作已被用户取消

以下是已引发的异常:

System.Security.Cryptographics.CryptographicException.ThrowCryptographicException(Int32 hr) 在System.Security.Cryptography.Utils.SignValue(SafeKeyHandle hKey、Int32 keyNumber、Int32 calgKey、Int32 calgHash、Byte[]散列、Int32 cbHash、ObjectHandleOnStack retSignature) at System.Security.Cryptography.Utils.SignValue(SafeKeyHandle hKey、Int32 keyNumber、Int32 calgKey、Int32 calgHash、Byte[]散列) 位于System.Security.Cryptography.RSACryptoServiceProvider.SignHash(字节[]rgbHash,Int32 calgHash) 在System.Security.Cryptography.Xml.SignedXml.ComputeSignature()中

release/debug
上获得此错误的唯一方法是取消请求
PIN
的窗口。 是否有另一种方法来计算
签名
并将其应用于
XML
?这是我到目前为止唯一能找到的

它可能是一个
IIS
设置,但我尝试了各种方法都没有效果。如果勾选了客户端上的
SSL
,并将其设置为
Accept
,则可以找到证书,如图所示:

我还尝试导出我在各种帖子上看到的
私钥
,但是,因为它是
智能卡
,我无法导出
私钥
,我只能使用它,这就是我对代码所做的


一旦我启动了应用程序的这一部分,它首先会请求
证书
PIN
,并返回相同的错误。在随后的尝试中,它从不要求提供
PIN
证书

将应用程序池标识更改为windows帐户

请阅读您的帖子并更好地描述您的问题。听起来这段代码在第一次运行后又失败了。我怀疑是cookie导致了您的问题,但需要更好的描述。谢谢jdweng。我已经编辑了这个问题。请让我知道,如果它需要更多的澄清。它是否工作,如果你发布,然后安装在同一台机器上,它是建立在。让我们了解这是一个发布问题还是未在IIS上工作。在IIS上,您只有来宾权限,无法读取/写入文件。我假设智能卡在客户端机器上,而不是IIS上。尝试使用任何CPU构建。客户端和服务器上的Windows版本。在升级操作系统时,我发现RSA存在许多问题。似乎存在从32位加密到64位加密的问题。见:嗨,jdweng。我已经在运行VisualStudio的同一台机器上发布了它。智能卡已插入并成功读取。它在我打印日志时获取证书和私钥。这两个操作系统显然是相同的,因为我在Visual Studio的localhost上运行应用程序,而在IIS上运行另一个应用程序。一旦使用setup.exe发布和安装,无论生成计算机是否为Win 7,部署计算机是否为Win 10,“都不应该”重要。现在,我不能完全确定网络库中是否存在被破坏的加密功能。我最近看到了一些问题,不知道但还没有找到根本原因。在一个案例中,代码中断了从Net4.2的升级。我的最佳猜测是网络库中的32位加密和64位加密。您是否在IIS上以管理员身份运行setup.exe。构建和部署计算机是否具有完全相同的Net版本?谢谢,但它仍然给出与上面相同的错误。