生成具有特定命名空间前缀(“ds:”)的数字签名

我对XML文件进行数字签名,但需要签名标记包含名称空间前缀“ds”。我仔细研究了谷歌,发现了许多相同的问题,但没有令人满意的答案

我试图手动将“ds”放入文件中,但签名无效。标记“SignatureValue”对标记“SignedInfo”进行签名,因此签名无效

有人能告诉我如何生成标记“SignatureValue”的值,以便在添加前缀“ds”后替换签名吗

显然很多人都遇到了同样的问题。在调查了类签名的源代码之后,我得出结论,微软旨在帮助我们。方法LoadXml()中有硬编码前缀“ds”。所以,可以生成签名,然后向其添加名称空间前缀“ds”,加载修改后的签名并重新计算“SignatureValue”。不幸的是,库中的bug让事情变得有点困难。下面是带有变通方法和注释的代码

公共静态无效SignXml(XmlDocument xmlDoc,X509Certificate2 cert)
{
//转换证书->密钥省略
rsa加密服务提供者密钥;
//创建SignedXml对象。
SignedXml SignedXml=新的SignedXml(xmlDoc);
//将密钥添加到SignedXml文档。
signedXml.SigningKey=key;
signedXml.SignedInfo.SignatureMethod=”http://www.w3.org/2001/04/xmldsig-more#rsa-sha256”;
signedXml.SignedInfo.CanonicalizationMethod=signedXml.XmlDsigExcC14NTransformUrl;
//创建要签名的引用。
引用=新引用();
reference.Uri=“#foo”;
reference.DigestMethod=”http://www.w3.org/2001/04/xmlenc#sha256";
//将包络变换添加到引用。
AddTransform(新的XMLDSIGenveledSignatureTransform());
AddTransform(新的XmlDsigExcC14NTransform());
signedXml.AddReference(参考);
KeyInfo KeyInfo=新的KeyInfo();
KeyInfoX509Data keyInfoData=新的KeyInfoX509Data();
keyInfoData.AddIssuerSerial(cert.IssuerName.Format(false)、cert.SerialNumber);
keyInfo.add子句(keyInfoData);
signedXml.KeyInfo=KeyInfo;
//计算签名。
signedXml.ComputeSignature();
//在签名中添加前缀“ds:”
xmlement signature=signedXml.GetXml();
SetPrefix(“ds”,签名);
//加载修改后的签名
signedXml.LoadXml(签名);
//这是克服库中错误的变通方法
signedXml.SignedInfo.References.Clear();
//重新计算签名
signedXml.ComputeSignature();
string recomputedSignature=Convert.ToBase64String(signedXml.SignatureValue);
//用重新计算的值替换签名的值
替换签名(签名、重新计算签名);
//将签名附加到XML文档。
xmlDoc.DocumentElement.InsertAfter(xmlDoc.ImportNode(签名,true),xmlDoc.DocumentElement.FirstChild);
}
私有静态void SetPrefix(字符串前缀,XmlNode节点)
{
node.Prefix=前缀;
foreach(node.ChildNodes中的XmlNode)
{
SetPrefix(前缀,n);
}
}
私有静态void ReplaceSignature(XmlElement签名,字符串newValue)
{
如果(signature==null)抛出新的ArgumentNullException(nameof(signature));
如果(signature.OwnerDocument==null)抛出新的ArgumentException(“无所有者文档”,nameof(signature));
XmlNamespaceManager nsm=新的XmlNamespaceManager(signature.OwnerDocument.NameTable);
AddNamespace(“ds”,SignedXml.XmlDsigNamespaceUrl);
XmlNode signatureValue=签名。选择SingleNode(“ds:signatureValue”,nsm);
if(signatureValue==null)
抛出新异常(“签名不包含'ds:SignatureValue'”);
signatureValue.InnerXml=newValue;
}

发表评论