c# - 用户在使用数字签名的应用程序中取消了操作
问题描述
的想法web app
是使用digital signature
从smart card
.
它已发布并设置为在local user
机器上工作。我正在IIS
为此设置bindings
并启用接受client certificates
。
它与web app
托管在cloud
.
我也成功地certificate
从 thesmart card
和 theprivate key
中得到了。
我用private key
来签署文件。
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
. 它得到 a popup
,要求 aPIN
并且一旦PIN
输入了文档就会被签名。
它到达signedxml.ComputeSignature
并返回一个错误:
该操作已被用户取消。
这是已引发的异常:
System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32 hr) 在 System.Security.Cryptography.Utils.SignValue(SafeKeyHandle hKey, Int32 keyNumber, Int32 calgKey, Int32 calgHash, Byte[] hash, Int32 cbHash, ObjectHandleOnStack retSignature) 在系统。 Security.Cryptography.Utils.SignValue(SafeKeyHandle hKey, Int32 keyNumber, Int32 calgKey, Int32 calgHash, Byte[] hash) 在 System.Security.Cryptography.RSACryptoServiceProvider.SignHash(Byte[] rgbHash, Int32 calgHash) 在 System.Security.Cryptography .Xml.SignedXml.ComputeSignature()
出现此错误的唯一方法release/debug
是取消要求PIN
. 是否有另一种方法来计算signature
并将其应用于XML
?这是迄今为止我能找到的唯一一个。
它可能是一个IIS
设置,但我尝试了各种方法都无济于事。如果我需要勾选,则可以找到证书并将其设置为SSL
如图所示:Client Side
Accept
我也尝试导出private key
我在各种帖子上看到的,但是,因为它是smart card
我无法导出的Private Key
,我只能使用它,这就是我对我的代码所做的。
一旦我启动应用程序的这一部分,它最初会询问certificate
和PIN
并返回相同的错误。在随后的尝试中,它从不要求PIN
或certificate
。
解决方案
将应用程序池标识更改为 Windows 帐户
推荐阅读
- bash - 使用带有bash的pcap拆分器拆分wireshark大尺寸
- c# - Cassandra 没有主机异常并且无法连接到任何服务器
- ldap - python-ldap django-auth-ldap 包中的错误
- service-worker - 更改 app.js 文件后,服务人员停止工作
- android - 当我使用 ListView 时,ListTile OnTap 正在工作。但是当我使用 ListWheelScrollView 它不起作用
- javascript - 寻找返回字符串位置的拆分变体
- c# - 使用 jquery 以表单形式发送输入数组
- python - 如何使用 python 代码创建与谷歌云实例的连接?
- java - 程序完成后 Java 挂起一分钟
- stenciljs - 创建新的 stenciljs 项目时出现错误“读取 ECONNRESET”。如何解决相同的问题?