XML 规范化算法在直接调用时与作为 xml 数字签名的一部分调用时给出两个不同的结果?

发布于 2024-07-24 23:09:36 字数 3723 浏览 11 评论 0原文

当我直接规范化某个 xml 时,与在对其执行数字签名时(在对 xml 进行散列之前也执行相同的规范化算法)相比,我得到了同一个 xml 文档的两个不同的哈希值? 我发现数字签名规范化在规范化时包括新行字符“\n”和空格字符,而直接算法则不包括。

包括换行符+空格不在规范化规范中? 我专门查看这个版本 http://www.w3.org /TR/2001/REC-xml-c14n-20010315

有谁知道发生了什么事? 我已经包含了 xml 文档和代码的两个实现,以便您可以看到。

这真的让我很困惑,我想知道为什么,我是否遗漏了一些明显的东西?

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

直接规范化代码

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

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

任何想法都很棒! 顺便说一下,这都是 C# 代码。

预先感

谢乔恩

I'm getting two different hashes of the same xml document when I directly canonicalize some xml than when I perform a digital signature on it which also performs the same canonicalization algoririth on the xml before hashing it? I worked out that the digital signature canonicalization includes the new line characters '\n' and spacing characters when canonicalizing and the direct algorithm does not.

Including the new line characters + spaces is not in the canonicalization specification though? I'm specifically looking at this version http://www.w3.org/TR/2001/REC-xml-c14n-20010315

Does anyone know what is going on? I've included the xml doc and both implementations of the code so you can see.

This is really puzzling me and I'd like to know why, am I missing something obvious?

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

The direct canonicalization code

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

The xml digital signature code

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

Any idea would be great! It's all C# code by the way.

Thanks in advance

Jon

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

时光清浅 2024-07-31 23:09:36

在我看来,XML Sig 处理空格的方式已经被破坏了。 这当然不符合大多数有正确思维的人所说的规范化。 更改空格不应影响摘要,但在 xmlsig 中却会影响摘要。

一种可能的解决方法是在将文档传递给签名生成代码之前将其传递给规范化器例程。 这应该会让事情变得更加可预测。

本文可能有助于澄清问题。

The way in which XML Sig handles whitespace is, in my opinion broken. It's certainly not compliant with what most right-thinking people would call canonicalization. Changing whitespace should not affect the digest, but in xmlsig, it does.

One possible workaround is to pass the document through a canonicalizer routine before passing it to the signature generation code. That should make things far more predictable.

This article might help clarify things.

如果没有你 2024-07-31 23:09:36

看起来在你的第二段代码中你有,

xmlDoc.PreserveWhitespace = true;

而在第一段代码中你没有。

据我了解,规范化规范要求保留元素之间的空白,因此我建议您在两者中都包含这一行。

It looks like in your second piece of code you have

xmlDoc.PreserveWhitespace = true;

while in the first you do not.

As I understand it, the canonicalisation specification asks to preserve the whitespace between elements, so I suggest you include this line in both.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文