我正在尝试使用XAdES对XML进行签名,证书存储在智能卡上。
首先,值得一提的是,当我用添加到智能卡的软件签署同一个XML文档时,操作没有任何问题。
代码如下:
public class XadesWrapper
{
private X509Certificate2 _certificate;
private X509Chain _chain;
private XmlDocument _envelopedSignatureXmlDocument;
private XadesSignedXml _xadesSignedXml;
private int _docDataObjectCounter;
public byte[] _signedDoc;
public XadesWrapper(XmlDocument xmlDoc, X509Certificate2 xCert)
{
try
{
_envelopedSignatureXmlDocument = xmlDoc;
_certificate = xCert; //certificate installed from smart card
AddReference();
CheckCertificate();
AddKeyInfo();
AddObjectInfo();
AddSignatureToDocument();
}
catch (Exception e)
{
throw e;
}
}
private void AddReference()
{
Reference reference = new Reference();
_docDataObjectCounter = 1;
_xadesSignedXml = new XadesSignedXml(_envelopedSignatureXmlDocument);
_xadesSignedXml.SignedInfo.CanonicalizationMethod = "http://www.w3.org/2001/10/xml-exc-c14n#";
reference.Id = "r-id-" + _docDataObjectCounter;
reference.Uri = "";
reference.Type = "";
reference.AddTransform(new XmlDsigEnvelopedSignatureTransform());
_xadesSignedXml.AddReference(reference);
}
private void CheckCertificate()
{
if (_certificate == null)
return;
_chain = new X509Chain();
_chain.ChainPolicy.RevocationFlag = X509RevocationFlag.EntireChain;
_chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
_chain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(0, 0, 30);
_chain.ChainPolicy.VerificationFlags = X509VerificationFlags.NoFlag;
if (_chain.Build(_certificate) == true)
AddKeyInfo();
else
{
_certificate = null;
_chain = null;
throw new ArgumentException("Chain is not valid.");
}
}
private void AddKeyInfo()
{
RSACryptoServiceProvider rsaKey = (RSACryptoServiceProvider)_certificate.PrivateKey;
_xadesSignedXml.SigningKey = rsaKey;
KeyInfo keyInfo = new KeyInfo();
keyInfo.AddClause(new KeyInfoX509Data(_certificate));
keyInfo.AddClause(new RSAKeyValue(rsaKey));
this._xadesSignedXml.KeyInfo = keyInfo;
}
private void AddObjectInfo()
{
_xadesSignedXml.Signature.Id = "id-" + _certificate.Thumbprint.ToLower();
XadesObject xadesObject = new XadesObject();
xadesObject.QualifyingProperties.Target = "#" + _xadesSignedXml.Signature.Id;
xadesObject.QualifyingProperties.SignedProperties.Id = "xades-" + _xadesSignedXml.Signature.Id;
Cert cert = new Cert();
cert.IssuerSerial.X509IssuerName = this._certificate.IssuerName.Name;
cert.IssuerSerial.X509SerialNumber = BigInteger.Parse(this._certificate.SerialNumber, NumberStyles.HexNumber).ToString();
cert.CertDigest.DigestMethod.Algorithm = "http://www.w3.org/2001/04/xmlenc#sha256";
cert.CertDigest.DigestValue = new SHA256CryptoServiceProvider().ComputeHash(_certificate.RawData);
xadesObject.QualifyingProperties.SignedProperties.SignedSignatureProperties.SigningCertificate.CertCollection.Add(cert);
xadesObject.QualifyingProperties.SignedProperties.SignedSignatureProperties.SigningTime = DateTime.Now;
DataObjectFormat newDataObjectFormat = new DataObjectFormat();
newDataObjectFormat.Description = "";
newDataObjectFormat.MimeType = "text/xml";
newDataObjectFormat.ObjectReferenceAttribute = "#r-id-" + _docDataObjectCounter;
xadesObject.QualifyingProperties.SignedProperties.SignedDataObjectProperties.DataObjectFormatCollection.Add(newDataObjectFormat);
_xadesSignedXml.AddXadesObject(xadesObject);
}
private void AddSignatureToDocument()
{
_xadesSignedXml.ComputeSignature();
_xadesSignedXml.SignatureValueId = "value-" + _xadesSignedXml.Signature.Id;
_envelopedSignatureXmlDocument.DocumentElement.AppendChild(_envelopedSignatureXmlDocument.ImportNode(_xadesSignedXml.GetXml(), true));
_signedDoc = Encoding.UTF8.GetBytes(_envelopedSignatureXmlDocument.OuterXml);
}
}
在执行到达AddSignatureToDocument()方法中的line _xadesSignedXml.ComputeSignature()之前,一切正常。
系统要求提供智能卡PIN QSCD,然后ComputeSignature()抛出CryptographicException(),并显示HRESULT -2146435068(0x 80100004)和消息“无法正确解释一个或多个提供的参数”。
下面是调用堆栈:
at System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32 hr)
at System.Security.Cryptography.Utils.SignValue(SafeKeyHandle hKey, Int32 keyNumber, Int32 calgKey, Int32 calgHash, Byte[] hash, Int32 cbHash, ObjectHandleOnStack retSignature)
at System.Security.Cryptography.Utils.SignValue(SafeKeyHandle hKey, Int32 keyNumber, Int32 calgKey, Int32 calgHash, Byte[] hash)
at System.Security.Cryptography.RSACryptoServiceProvider.SignHash(Byte[] rgbHash, Int32 calgHash)
at System.Security.Cryptography.RSAPKCS1SignatureFormatter.CreateSignature(Byte[] rgbHash)
at System.Security.Cryptography.AsymmetricSignatureFormatter.CreateSignature(HashAlgorithm hash)
at Microsoft.Xades.XadesSignedXml.ComputeSignature()
1条答案
按热度按时间f8rj6qna1#
所以我找到了解决办法:xadesSignedXml元素的
xadesSignedXml.SignedInfo.SignatureMethod
属性为空,而xadesSignedXml.SigningKey.SignatureAlgorithm
属性被自动设置为“http://www.w3.org/2000/09/xmldsig#rsa-sha1“。当
xadesSignedXml.ComputeSignature()
正在执行时,并且xadesSignedXml.SignedInfo.SignatureMethod
为空,则将xadesSignedXml.SigningKey.SignatureAlgorithm
的值分配给它。出现此问题是因为签名是使用SHA-1执行的,而Microsoft不再支持SHA-1。
通过在
AddReference()
方法中添加xadesSignedXml.SignedInfo.SignatureMethod = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";
解决了问题。