2009-06-22 8 views
8

Tôi nhận được hai băm khác nhau của cùng một tài liệu xml khi tôi trực tiếp hợp chuẩn hóa một số xml hơn khi tôi thực hiện chữ ký số trên nó cũng thực hiện cùng một thuật toán kinh điển trên xml trước khi băm nó? Tôi đã làm việc ra rằng canonicalization chữ ký kỹ thuật số bao gồm các ký tự dòng mới '\ n' và khoảng cách ký tự khi canonicalizing và thuật toán trực tiếp không.Thuật toán Canonicalization XML cung cấp hai kết quả khác biệt khi được gọi trực tiếp hơn khi được gọi là một phần của chữ ký số xml?

Bao gồm các ký tự dòng mới + dấu cách không nằm trong đặc điểm kỹ thuật chuẩn hóa? Tôi đặc biệt đang xem phiên bản này http://www.w3.org/TR/2001/REC-xml-c14n-20010315

Có ai biết điều gì đang xảy ra không? Tôi đã bao gồm tài liệu xml và cả hai triển khai mã để bạn có thể thấy.

Điều này thực sự khiến tôi khó hiểu và tôi muốn biết tại sao, tôi thiếu một điều gì đó hiển nhiên?

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

Mã canonicalization trực tiếp

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

Chữ ký số xml đang

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

Bất cứ ý tưởng sẽ là tuyệt vời! Đó là tất cả mã C# bằng cách này.

Cảm ơn trước

Jon

Trả lời

7

Cách thức mà XML Sig xử lý khoảng trắng là, theo ý kiến ​​của tôi bị hỏng. Nó chắc chắn không phù hợp với những gì mà những người nghĩ đúng nhất sẽ gọi là canonicalization. Thay đổi khoảng trắng nên không phải ảnh hưởng đến thông báo, nhưng trong xmlsig, nó có.

Một cách giải quyết khác là chuyển tài liệu qua quy trình chuẩn hóa trước khi chuyển nó tới mã tạo chữ ký. Điều đó sẽ làm cho mọi thứ dễ dự đoán hơn.

This article có thể giúp làm rõ mọi thứ.

+0

Ahh, do đó, vấn đề không phải là với thuật toán C14n chính nó spec chữ ký số xml-spec specifys khoảng trắng và ký tự dòng mới để duy trì trong khi canonicalizing tài liệu? Đây là một cạm bẫy mà tôi không biết. Tôi sẽ cố gắng gợi ý của bạn về canonocalizing xml trước khi chuyển nó cho người ký tên. Đây chắc chắn là logic ngược, W3c mất tất cả thời gian sắp tới với thông số kỹ thuật để lấy bất kỳ tài liệu xml nào thành một hình thức can thiệp và sau đó mâu thuẫn với thông số chữ ký số xml-kỹ thuật số? Có vẻ rất lạ. Bạn có biết lý do tại sao điều này là? Cảm ơn sự giúp đỡ của bạn! – Jon

0

Dường như ở mảnh thứ hai của bạn mã bạn có

xmlDoc.PreserveWhitespace = true; 

trong khi trong lần đầu tiên bạn không.

Như tôi đã hiểu, đặc điểm kỹ thuật chuẩn hóa yêu cầu bảo toàn khoảng trống giữa các phần tử, vì vậy tôi đề nghị bạn nên đưa dòng này vào cả hai.