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版本?谢谢,但它仍然给出与上面相同的错误。