2009-10-05 117 views
7

在C#中散列XML文檔的最佳方式是什麼?我想散列一個XML文檔,以便我可以判斷它是否是從生成時手動更改的。我沒有使用它來保證安全性 - 如果有人更改了XML,並且更改了哈希以匹配,那麼也沒關係。在C#中生成XML文檔哈希#

例如,我湊根的子節點和散列存儲爲根的一個屬性:

<RootNode Hash="abc123"> 
    <!-- Content to hash here --> 
</RootNode> 
+0

空白在你想要的散列中起什麼作用? –

+0

我對此很感興趣 - 一方面,我只關心數據,而不是格式化。另一方面,識別*任何*更改可能有助於檢查是否有人在玩弄文件。 –

回答

7

.NET有classes實現XML digital signature spec。簽名可以添加到原始XML文檔中(即「封裝簽名」),也可以單獨存儲/傳輸。

這可能有點矯枉過正,因爲您不需要安全性,但它具有已經實現的優點,並且是一種不依賴於語言或平臺的標準。

+0

我喜歡這個解決方案,因爲正如您所指出的那樣,它已經實施並且是一個標準。 –

4

您可以使用加密命名空間:

System.Security.Cryptography.MACTripleDES hash = new System.Security.Cryptography.MACTripleDES(Encoding.Default.GetBytes("mykey")); 
string hashString = Convert.ToBase64String(hash.ComputeHash(Encoding.Default.GetBytes(myXMLString))); 

你只需要使用一個鍵來創建散列密碼,然後用你的xml的字符串reqpresentation創建一個散列。

+1

另請參閱System.Security.Cryptography.MD5,System.Security.Cryptography.SHA1,System.Security.Cryptography.SHA256等,並在此處查看比較:http://en.wikipedia.org/wiki/Cryptographic_hash_function –

+2

編碼。默認值是操作系統當前ANSI代碼頁的編碼。因此,您的代碼將根據「區域和語言選項 - 高級」選項卡中的設置給出不同的結果。 –

+0

wcoenen有一個非常公平的點。使用Encoding.ASCII或編碼<一些​​一致的編碼>。 –

2

添加對System.Security的.NET引用,並使用XmlDsigC14NTransform。下面是一個例子...

/* http://www.w3.org/TR/xml-c14n 

    Of course is cannot detect these are the same... 

     <color>black</color> vs. <color>rgb(0,0,0)</color> 

    ...because that's dependent on app logic's interpretation of XML data. 

    But otherwise it gets the following right... 
    •Normalization of whitespace in start and end tags 
    •Lexicographic ordering of namespace and attribute 
    •Empty element conversion to start-end tag pair 
    •Retain all whitespace between tags 

    And more. 
*/ 
public static string XmlHash(XmlDocument myDoc) 
{ 
    var t = new System.Security.Cryptography.Xml.XmlDsigC14NTransform(); 
    t.LoadInput(myDoc); 
    var s = (Stream)t.GetOutput(typeof(Stream)); 
    var sha1 = SHA1.Create(); 

    var hash = sha1.ComputeHash(s); 
    var base64String = Convert.ToBase64String(hash); 
    s.Close(); 
    return base64String; 
}