XML Canonicalizationアルゴリズムは、xmlデジタル署名の一部として呼び出された場合と直接呼び出された場合の2つの異なる結果を提供しますか?
-
06-07-2019 - |
質問
いくつかの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#コードです。
事前に感謝
ジョン
解決
XML Sigが空白を処理する方法は、私の意見では壊れています。確かに、最も正しい考えを持つ人々が標準化と呼ぶものに準拠していません。空白の変更はダイジェストに影響を与えるべきではありませんが 、xmlsigでは影響します。
可能な回避策の1つは、署名生成コードに渡す前に、canonicalizerルーチンにドキュメントを渡すことです。これにより、物事がはるかに予測可能になります。
この記事が役立つ場合があります物事を明確にします。
他のヒント
2つ目のコードのように見えます
xmlDoc.PreserveWhitespace = true;
最初はそうではありません。
理解しているように、正規化仕様では要素間の空白を保持するように求められているため、この行を両方に含めることをお勧めします。