L'algorithme XML de canonisation donne deux résultats différents lorsqu'il est appelé directement que lorsqu'il est appelé dans le cadre d'une signature numérique XML

StackOverflow https://stackoverflow.com/questions/1026432

Question

J'obtiens deux hachages différents du même document XML lorsque je canonise directement du XML que lorsque j'exécute une signature numérique sur celui-ci qui effectue également le même algorithme de canonisation sur le XML avant de le hacher? J'ai travaillé sur le fait que la canonisation de la signature numérique inclut les caractères de nouvelle ligne '\ n' et les caractères d'espacement lors de la canonisation, contrairement à l'algorithme direct.

Inclure les caractères de nouvelle ligne + les espaces ne fait pas partie de la spécification de canonisation? Je regarde spécifiquement cette version http://www.w3.org / TR / 2001 / REC-xml-c14n-20010315

Est-ce que quelqu'un sait ce qui se passe? J'ai inclus le document XML et les deux implémentations du code afin que vous puissiez voir.

Cela me laisse vraiment perplexe et j'aimerais savoir pourquoi il me manque quelque chose d'évident?

<root>
  <child1>some text</child1>
  <child2 attr="1" />
</root>

Le code de canonisation directe

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Security.Cryptography.Xml;
using System.Security.Cryptography;
using System.IO;
using System.ComponentModel;

namespace XML_SignatureGenerator
{
    class XML_C14N
    {
        private String _filename;
        private Boolean isCommented = false;
        private XmlDocument xmlDoc = null;

        public XML_C14N(String filename)
        {
            _filename = filename;
            xmlDoc = new XmlDocument();
            xmlDoc.Load(_filename);
        }

        //implement this spec http://www.w3.org/TR/2001/REC-xml-c14n-20010315
        public String XML_Canonalize(System.Windows.Forms.RichTextBox tb)
        {
            //create c14n instance and load in xml file
            XmlDsigC14NTransform c14n = new XmlDsigC14NTransform(isCommented);

            c14n.LoadInput(xmlDoc);

            //get canonalised stream
            Stream s1 = (Stream)c14n.GetOutput(typeof(Stream));
            SHA1 sha1 = new SHA1CryptoServiceProvider();
            Byte[] output = sha1.ComputeHash(s1);

            tb.Text = Convert.ToBase64String(output);

            //create new xmldocument and save
            String newFilename = _filename.Substring(0, _filename.Length - 4) + "C14N.xml";
            XmlDocument xmldoc2 = new XmlDocument();
            xmldoc2.Load(s1);
            xmldoc2.Save(newFilename);

            return newFilename;
        }

        public void set_isCommented(Boolean value)
        {
            isCommented = value;
        }

        public Boolean get_isCommented()
        {
            return isCommented;
        }
    }
}

Le code de signature numérique xml

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

namespace XML_SignatureGenerator
{
class xmlSignature
    {
        public xmlSignature(String filename)
        {
            _filename = filename;
        }

        public Boolean SignXML()
        {
            RSACryptoServiceProvider rsa =  new RSACryptoServiceProvider();
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.PreserveWhitespace = true;
            String fname = _filename; //"C:\\SigTest.xml";
            xmlDoc.Load(fname);

            SignedXml xmlSig = new SignedXml(xmlDoc);
            xmlSig.SigningKey = rsa;

            Reference reference = new Reference();
            reference.Uri = "";

            XmlDsigC14NTransform env = new XmlDsigC14NTransform(false);
            reference.AddTransform(env);

            xmlSig.AddReference(reference);
            xmlSig.ComputeSignature();

            XmlElement xmlDigitalSignature = xmlSig.GetXml();
            xmlDoc.DocumentElement.AppendChild(xmlDoc.ImportNode(xmlDigitalSignature, true));

            xmlDoc.Save(Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "/SignedXML.xml");

            return true;
        }
        private String _filename;
    }
}

Toute idée serait géniale! C'est tout le code C # au fait.

Merci d'avance

Jon

Était-ce utile?

La solution

À mon avis, la façon dont XML Sig gère les espaces est cassée. Ce n'est certainement pas conforme à ce que la plupart des gens de droit droit appellent la canonisation. La modification des espaces ne doit pas affecter le résumé, mais dans xmlsig, elle le fait.

Une solution de contournement possible consiste à faire passer le document par une routine canonicalizer avant de le transmettre au code de génération de signature. Cela devrait rendre les choses beaucoup plus prévisibles.

Cet article pourrait vous aider clarifier les choses.

Autres conseils

Cela ressemble à votre deuxième morceau de code que vous avez

xmlDoc.PreserveWhitespace = true;

alors que dans le premier cas, vous ne le faites pas.

Si je comprends bien, la spécification de canonisation demande de conserver les espaces entre les éléments. Je vous suggère donc d'inclure cette ligne dans les deux.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top