L'algoritmo XML Canonicalization fornisce due risultati di differenza quando viene chiamato direttamente rispetto a quando viene chiamato come parte di una firma digitale xml?

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

Domanda

Ricevo due diversi hash dello stesso documento XML quando canonicalizzo direttamente alcuni XML rispetto a quando eseguo una firma digitale su di esso che esegue anche lo stesso algoritmo di canonizzazione sull'XML prima di eseguire l'hashing? Ho scoperto che la canonicalizzazione della firma digitale include i nuovi caratteri di riga '\ n' e i caratteri di spaziatura durante la canonicalizzazione e l'algoritmo diretto no.

L'inclusione della nuova riga caratteri + spazi non è tuttavia nelle specifiche di canonicalizzazione? Sto esaminando specificamente questa versione http://www.w3.org / TR / 2001 / REC-xml-C14N-20.010.315

Qualcuno sa cosa sta succedendo? Ho incluso il documento xml ed entrambe le implementazioni del codice in modo che tu possa vedere.

Questo mi sta davvero sconcertando e mi piacerebbe sapere perché, mi sto perdendo qualcosa di ovvio?

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

Il codice di canonicalizzazione diretta

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;
        }
    }
}

Il codice della firma digitale 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;
    }
}

Qualsiasi idea sarebbe fantastica! A proposito, è tutto codice C #.

Grazie in anticipo

Jon

È stato utile?

Soluzione

Il modo in cui XML Sig gestisce gli spazi bianchi, a mio avviso, è rotto. Certamente non è conforme a ciò che la maggior parte delle persone che pensano bene chiamerebbe canonicalizzazione. Cambiare spazio bianco dovrebbe non influenzare il digest, ma in xmlsig, lo fa.

Una possibile soluzione alternativa è passare il documento attraverso una routine canonicalizer prima di passarlo al codice di generazione della firma. Ciò dovrebbe rendere le cose molto più prevedibili.

Questo articolo potrebbe aiutare chiarire le cose.

Altri suggerimenti

Sembra che tu abbia il tuo secondo pezzo di codice

xmlDoc.PreserveWhitespace = true;

mentre nel primo non lo fai.

A quanto ho capito, la specifica di canonicalizzazione chiede di preservare lo spazio bianco tra gli elementi, quindi suggerisco di includere questa linea in entrambi.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top