Xml DS signature prefix?

Is there a way to sign an XML file with RSA and have the namespace prefix "ds: Signature" instead of "Signature"? I spent many hours to solve this problem, and from what I see there is no solution.

It seems to be hardcoded in the System.Security.Cryptography.Xml.Signature class.

XmlElement element = document.CreateElement("Signature", "http://www.w3.org/2000/09/xmldsig#");

If someone knows the solution, I need to sign it, because the import of the software checks it with "ds: signature", so with the prefix "ds" the software checks it as follows:

    public static bool VerifySignature(XmlDocument doc, RSA key, string prefix)
    {
        SignedXml xml = new SignedXml(doc);
        string str = "Signature";
        if (!string.IsNullOrEmpty(prefix))
        {
            str = string.Format("{0}:{1}", prefix, str);
        }
        XmlNodeList elementsByTagName = doc.GetElementsByTagName(str);
        xml.LoadXml((XmlElement)elementsByTagName[0]);
        return xml.CheckSignature(key);
    }

  VerifySignature(xmlDoc, rsa, "ds");

it is usually signed as follows:

<kk>blabla<Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /><SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" /><Reference URI=""><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /></Transforms><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /><DigestValue>rVL2nKjPTBhL9IDHYpu69OiE8gI=</DigestValue></Reference></SignedInfo><SignatureValue>CfXW9D/ErmHjzxIjy0/54/V3nst6j/XXcu7keR17LApfOZEpxjEvAlG3VnBZIi3jxQzU6t9RkmfDyngcRZccJByuuA6YDwFTQxZNRgu2GRoZxMKWnkm+MtQ0jH0Fo78GivCxV+iIewZvsrUQLzG01cXuZSH/k2eeMUaEooJaLQiYpO2aNVn5xbosTPtGlsACzFWz34E69/ZeeLZbXLc3jpDO+opxdYJ5e+Tnk/UM2Klt+N+m7Gh/sUNTPgkDiwP3q3y3O9tvCT0G2XmQaWBP4rw9TIoYHQtucm2b8R2JeggbeRKOetbRYV218RT8CK2Yuy0FIUlQXdabKyp9F96Yc55g8eNe10FGtgietH2iqquIVFLCA8fu3SZNLDPMoyHnVNKdBvI35+S8hrAaybEkMvo7iYnUSY5KrlGSfGGtfQXdaISutAzcnGPDFXgZXPNzNy7eL0u+Lt3yWWkj7wh6Zeh4fH2+nXDWYCWbLpegAEX4ZWSI5Ts6D1TplMJTGH1F0GyflehH4u+W4Lc3TvkB4dWjEuiKgnpl3hcvoj2CWFaeAxXMd/64tU/YMm8+1gSBjkVH6oV+QlI/m0z6M8FPVEVC2as0wLG2woVwmzVLcaQKyPi7NN4eO9ea7QNfaRHaofU4LQO/Y3FNJOP+uMfYlGJKWSr3qv29+BQjeNldNJY=</SignatureValue></Signature></kk>

and I need to do this as follows:

<kk>blabla<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:SignedInfo><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /><ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" /><ds:Reference URI=""><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /><ds:DigestValue>rVL2nKjPTBhL9IDHYpu69OiE8gI=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>CfXW9D/ErmHjzxIjy0/54/V3nst6j/XXcu7keR17LApfOZEpxjEvAlG3VnBZIi3jxQzU6t9RkmfDyngcRZccJByuuA6YDwFTQxZNRgu2GRoZxMKWnkm+MtQ0jH0Fo78GivCxV+iIewZvsrUQLzG01cXuZSH/k2eeMUaEooJaLQiYpO2aNVn5xbosTPtGlsACzFWz34E69/ZeeLZbXLc3jpDO+opxdYJ5e+Tnk/UM2Klt+N+m7Gh/sUNTPgkDiwP3q3y3O9tvCT0G2XmQaWBP4rw9TIoYHQtucm2b8R2JeggbeRKOetbRYV218RT8CK2Yuy0FIUlQXdabKyp9F96Yc55g8eNe10FGtgietH2iqquIVFLCA8fu3SZNLDPMoyHnVNKdBvI35+S8hrAaybEkMvo7iYnUSY5KrlGSfGGtfQXdaISutAzcnGPDFXgZXPNzNy7eL0u+Lt3yWWkj7wh6Zeh4fH2+nXDWYCWbLpegAEX4ZWSI5Ts6D1TplMJTGH1F0GyflehH4u+W4Lc3TvkB4dWjEuiKgnpl3hcvoj2CWFaeAxXMd/64tU/YMm8+1gSBjkVH6oV+QlI/m0z6M8FPVEVC2as0wLG2woVwmzVLcaQKyPi7NN4eO9ea7QNfaRHaofU4LQO/Y3FNJOP+uMfYlGJKWSr3qv29+BQjeNldNJY=</ds:SignatureValue></ds:Signature></kk>
+5
source share
6 answers

- , , "ds: signature", "ds"

- , , - , . , . , , .

, , - , , , ? LINQ to XML.

+8

using System;
using System.Reflection;
using System.Security.Cryptography.Xml;
using System.Security.Cryptography;
using System.Collections.Generic;
using System.Text;
using System.Xml;

namespace mysign
{
public class PrefixedSignedXML : SignedXml
{
    public PrefixedSignedXML(XmlDocument document)
        : base(document)
    { }

    public PrefixedSignedXML(XmlElement element)
        : base(element)
    { }

    public PrefixedSignedXML()
        : base()
    { }

    public void ComputeSignature(string prefix)
    {
        this.BuildDigestedReferences();
        AsymmetricAlgorithm signingKey = this.SigningKey;
        if (signingKey == null)
        {
            throw new CryptographicException("Cryptography_Xml_LoadKeyFailed");
        }
        if (this.SignedInfo.SignatureMethod == null)
        {
            if (!(signingKey is DSA))
            {
                if (!(signingKey is RSA))
                {
                    throw new CryptographicException("Cryptography_Xml_CreatedKeyFailed");
                }
                if (this.SignedInfo.SignatureMethod == null)
                {
                    this.SignedInfo.SignatureMethod = "http://www.w3.org/2000/09/xmldsig#rsa-sha1";
                }
            }
            else
            {
                this.SignedInfo.SignatureMethod = "http://www.w3.org/2000/09/xmldsig#dsa-sha1";
            }
        }
        SignatureDescription description = CryptoConfig.CreateFromName(this.SignedInfo.SignatureMethod) as SignatureDescription;
        if (description == null)
        {
            throw new CryptographicException("Cryptography_Xml_SignatureDescriptionNotCreated");
        }
        HashAlgorithm hash = description.CreateDigest();
        if (hash == null)
        {
            throw new CryptographicException("Cryptography_Xml_CreateHashAlgorithmFailed");
        }
        this.GetC14NDigest(hash, prefix);
        this.m_signature.SignatureValue = description.CreateFormatter(signingKey).CreateSignature(hash);
    }

    public XmlElement GetXml(string prefix)
    {
        XmlElement e = this.GetXml();
        SetPrefix(prefix, e);
        return e;
    }

    //Invocar por reflexión al método privado SignedXml.BuildDigestedReferences
    private void BuildDigestedReferences()
    {
        Type t = typeof(SignedXml);
        MethodInfo m = t.GetMethod("BuildDigestedReferences", BindingFlags.NonPublic | BindingFlags.Instance);
        m.Invoke(this, new object[] { });
    }

    private byte[] GetC14NDigest(HashAlgorithm hash, string prefix)
    {
        //string securityUrl = (this.m_containingDocument == null) ? null : this.m_containingDocument.BaseURI;
        //XmlResolver xmlResolver = new XmlSecureResolver(new XmlUrlResolver(), securityUrl);
        XmlDocument document = new XmlDocument();
        document.PreserveWhitespace = true;
        XmlElement e = this.SignedInfo.GetXml();
        document.AppendChild(document.ImportNode(e, true));
        //CanonicalXmlNodeList namespaces = (this.m_context == null) ? null : Utils.GetPropagatedAttributes(this.m_context);
        //Utils.AddNamespaces(document.DocumentElement, namespaces);

        Transform canonicalizationMethodObject = this.SignedInfo.CanonicalizationMethodObject;
        //canonicalizationMethodObject.Resolver = xmlResolver;
        //canonicalizationMethodObject.BaseURI = securityUrl;
        SetPrefix(prefix, document.DocumentElement); //establecemos el prefijo antes de se que calcule el hash (o de lo contrario la firma no será válida)
        canonicalizationMethodObject.LoadInput(document);
        return canonicalizationMethodObject.GetDigestedOutput(hash);
    }

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

, . , .NET(http://referencesource.microsoft.com/), , , XmlDocument SignedXml, . "ds" "SignedInfo" siganture. , , :


XmlDsigDocument.cs

using System;
using System.Collections.Generic;
using System.Security.Cryptography.Xml;
using System.Text;
using System.Xml;

namespace CustomSecurity
{
class XmlDsigDocument : XmlDocument
{
    // Constants
    public const string XmlDsigNamespacePrefix = "ds";

    /// <summary>
    /// Override CreateElement function as it is extensively used by SignedXml
    /// </summary>
    /// <param name="prefix"></param>
    /// <param name="localName"></param>
    /// <param name="namespaceURI"></param>
    /// <returns></returns>
    public override XmlElement CreateElement(string prefix, string localName, string namespaceURI)
    {
        // CAntonio. If this is a Digital signature security element, add the prefix. 
        if (string.IsNullOrEmpty(prefix))
        {
            // !!! Note: If you comment this line, you'll get a valid signed file! (but without ds prefix)
            // !!! Note: If you uncomment this line, you'll get an invalid signed file! (with ds prefix within 'Signature' object)
            //prefix = GetPrefix(namespaceURI);

            // The only way to get a valid signed file is to prevent 'Prefix' on 'SignedInfo' and descendants.
            List<string> SignedInfoAndDescendants = new List<string>();
            SignedInfoAndDescendants.Add("SignedInfo");
            SignedInfoAndDescendants.Add("CanonicalizationMethod");
            SignedInfoAndDescendants.Add("InclusiveNamespaces");
            SignedInfoAndDescendants.Add("SignatureMethod");
            SignedInfoAndDescendants.Add("Reference");
            SignedInfoAndDescendants.Add("Transforms");
            SignedInfoAndDescendants.Add("Transform");
            SignedInfoAndDescendants.Add("InclusiveNamespaces");
            SignedInfoAndDescendants.Add("DigestMethod");
            SignedInfoAndDescendants.Add("DigestValue");
            if (!SignedInfoAndDescendants.Contains(localName))
            {
                prefix = GetPrefix(namespaceURI);
            }
        }

        return base.CreateElement(prefix, localName, namespaceURI);
    }

    /// <summary>
    /// Select the standar prefix for the namespaceURI provided
    /// </summary>
    /// <param name="namespaceURI"></param>
    /// <returns></returns>
    public static string GetPrefix(string namespaceURI)
    {
        if (namespaceURI == "http://www.w3.org/2001/10/xml-exc-c14n#")
            return "ec";
        else if (namespaceURI == SignedXml.XmlDsigNamespaceUrl)
            return "ds";

        return string.Empty;
    }
}
}

SignedXml:

    // Create a new XML document.
    XmlDsigDocument doc = new XmlDsigDocument();

    // Load the passed XML file using its name.
    doc.Load(new XmlTextReader(FileName));

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

:

https://social.msdn.microsoft.com/Forums/en-US/cd595379-f66a-49c8-8ca2-62acdc58b252/add-prefixds-signedxml?forum=xmlandnetfx

+1

, SetPrefix :

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

, , ...

XML #, XPath:

var s = signedXml.GetXml();
XmlNodeList nodes = s.SelectNodes("descendant-or-self::*");
foreach (XmlNode childNode in nodes)
{
    childNode.Prefix = "dsig";
}
0

George Dima .

, .

ComputeSignature, Signature, SignedInfo node.

, , SignedInfo node , . XML

, signedinfo node

private byte[] GetC14NDigest(HashAlgorithm hash, string prefix)
{        
    XmlDocument document = new XmlDocument();
    document.PreserveWhitespace = true;
    XmlElement e = this.SignedInfo.GetXml();
    document.AppendChild(document.ImportNode(e, true));        
    Transform canonicalizationMethodObject = this.SignedInfo.CanonicalizationMethodObject;

    SetPrefix(prefix, document.DocumentElement); //HERE WHERE THE PREFIX IS ADDED TO GET THE DIGEST VALUE
    canonicalizationMethodObject.LoadInput(document);
    return canonicalizationMethodObject.GetDigestedOutput(hash);
}

, SignedInfo node , , xml , ,

signedXml.GetXml();

you will get xml without a prefix and, of course, because the signature value was calculated taking into account the ds prefix, you will have an invalid signature, so you need to call GetXml, passing it the prefix value, in this case "ds" like this

signedXml.GetXml("ds");
0
source

All Articles