8

いくつかの xml を直接正規化すると、ハッシュ化する前に xml で同じ正規化アルゴリズムを実行するデジタル署名を実行する場合よりも、同じ xml ドキュメントの 2 つの異なるハッシュが得られますか? デジタル署名の正規化には、正規化時に改行文字「\ 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# コードです。

前もって感謝します

ジョン

4

2 に答える 2

7

私の意見では、XML Sig が空白を処理する方法は壊れています。それは確かに、ほとんどの正しい考え方の人々が正規化と呼ぶものに準拠していません。空白を変更してもダイジェストには影響しませんが、xmlsig では影響します。

考えられる回避策の 1 つは、文書を署名生成コードに渡す前に、canonicalizer ルーチンを介して渡すことです。これにより、物事がはるかに予測可能になります。

この記事は、物事を明確にするのに役立つかもしれません。

于 2009-06-22T10:25:22.737 に答える
1

あなたが持っている2番目のコードのように見えます

xmlDoc.PreserveWhitespace = true;

最初はそうではありません。

私が理解しているように、正規化仕様は要素間の空白を保持するように求めているため、この行を両方に含めることをお勧めします。

于 2010-11-02T12:08:22.990 に答える