生成数字签名,但具有特定命名空间前缀(QUOT; DS:") [英] Generate Digital Signature but with a Specific Namespace Prefix ("ds:")

查看:1032
本文介绍了生成数字签名,但具有特定命名空间前缀(QUOT; DS:")的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我进行数字签名的XML文件,但需要标签包含命名空间前缀DS的签名。我研究比较了谷歌,发现很多相同的问题,但没有满意的答案。

I digitally sign XML files, but need the signature tags contain the namespace prefix "ds". I researched quite the google and found many of the same questions, but no satisfactory answer.

我试图把DS手动文件,但签名变得无效。标签的SignatureValue标志标签的SignedInfo,所以签名变为无效。

I tried to put the "ds" manually in the file, but the signature becomes invalid. The tag "SignatureValue" signs the tag "SignedInfo" so the signature becomes invalid.

有人能告诉我我该怎么生成标签的SignatureValue的值,这样我就可以加上前缀DS后更换签名?

Could somebody show me how I generate the value of the tag "SignatureValue" so I can replace the signature after adding the prefix "ds"?

推荐答案

显然,很多人都遇到同样的问题。调查类签名的源代码后,我来的结论,微软的目的是帮助我们。还有在方法loadXML的硬编码前缀DS()。这样,就有可能产生的签名,然后添加空间前缀DS到它,负载改性签名返回并重新计算的SignatureValue。可惜的是错误的库使事情有点难度比他们需要。与解决办法代码和注释如下。

Apparently a lot of people ran into the same problem. After investigating source code of the class Signature, I came to conclusion that Microsoft aimed to help us. There is hardcoded prefix "ds" in the method LoadXml(). So, it is possible to generate signature, then add namespace prefix "ds" to it, load modified signature back and recompute "SignatureValue". Unfortunatelly bug in the library makes things a bit harder than they need to be. The code with workaround and comments is below.

public static void SignXml(XmlDocument xmlDoc, X509Certificate2 cert)
{
        // transformation cert -> key omitted
        RSACryptoServiceProvider key;

        // Create a SignedXml object. 
        SignedXml signedXml = new SignedXml(xmlDoc);

        // Add the key to the SignedXml document. 
        signedXml.SigningKey = key;
        signedXml.SignedInfo.SignatureMethod = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";
        signedXml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NTransformUrl;

        // Create a reference to be signed. 
        Reference reference = new Reference();
        reference.Uri = "#foo";
        reference.DigestMethod = "http://www.w3.org/2001/04/xmlenc#sha256";
        // Add an enveloped transformation to the reference. 
        reference.AddTransform(new XmlDsigEnvelopedSignatureTransform());
        reference.AddTransform(new XmlDsigExcC14NTransform());
        signedXml.AddReference(reference);

        KeyInfo keyInfo = new KeyInfo();
        KeyInfoX509Data keyInfoData = new KeyInfoX509Data();
        keyInfoData.AddIssuerSerial(cert.IssuerName.Format(false), cert.SerialNumber);
        keyInfo.AddClause(keyInfoData);
        signedXml.KeyInfo = keyInfo;

        // Compute the signature. 
        signedXml.ComputeSignature();

        // Add prefix "ds:" to signature
        XmlElement signature = signedXml.GetXml();
        SetPrefix("ds", signature);

        // Load modified signature back
        signedXml.LoadXml(signature);

        // this is workaround for overcoming a bug in the library
        signedXml.SignedInfo.References.Clear();

        // Recompute the signature
        signedXml.ComputeSignature();
        string recomputedSignature = Convert.ToBase64String(signedXml.SignatureValue);

        // Replace value of the signature with recomputed one
        ReplaceSignature(signature, recomputedSignature);

        // Append the signature to the XML document. 
        xmlDoc.DocumentElement.InsertAfter(xmlDoc.ImportNode(signature, true), xmlDoc.DocumentElement.FirstChild);
    }

    private static void SetPrefix(string prefix, XmlNode node)
    {
        node.Prefix = prefix;
        foreach (XmlNode n in node.ChildNodes)
        {
            SetPrefix(prefix, n);
        }
    }

    private static void ReplaceSignature(XmlElement signature, string newValue)
    {
        if (signature == null) throw new ArgumentNullException(nameof(signature));
        if (signature.OwnerDocument == null) throw new ArgumentException("No owner document", nameof(signature));

        XmlNamespaceManager nsm = new XmlNamespaceManager(signature.OwnerDocument.NameTable);
        nsm.AddNamespace("ds", SignedXml.XmlDsigNamespaceUrl);

        XmlNode signatureValue = signature.SelectSingleNode("ds:SignatureValue", nsm);
        if (signatureValue == null)
            throw new Exception("Signature does not contain 'ds:SignatureValue'");

        signatureValue.InnerXml = newValue;
    }

这篇关于生成数字签名,但具有特定命名空间前缀(QUOT; DS:")的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆