2009-10-05 17 views
7

¿Cuál es la mejor manera de realizar hash un documento XML en C#? Me gustaría hacer un hash de un documento XML para poder decir si se cambió manualmente desde el momento en que se generó. No estoy usando esto para seguridad: está bien si alguien cambia el XML y cambia el hash para que coincida.Generar un hash de documento XML en C#

Por ejemplo, me gustaría hash los nodos secundarios de la raíz y almacenar el hash como un atributo de la raíz:

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

¿Cómo entran en juego los espacios en blanco en el hash deseado? –

+0

Estoy al margen sobre eso - por un lado, solo me importan los datos, no el formato. Por otro lado, identificar * cualquier * cambio podría ser útil para verificar si alguien estaba jugando con el archivo. –

Respuesta

7

.NET tiene classes que implementan XML digital signature spec. La firma se puede agregar dentro del documento XML original (es decir, una "firma envuelta"), o se puede almacenar/transferir por separado.

Puede ser un poco exagerado ya que no necesita la seguridad, pero tiene la ventaja de que ya está implementado, y es un estándar que no depende de un idioma o plataforma.

+0

Me gusta esta solución porque, como señaló, ya está implementada y es un estándar. –

4

Usted puede utilizar el espacio de nombres de la criptografía:

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

Solo necesita usar una clave para crear el criptógrafo de hashing y luego crear un hash con la representación de la cadena de su xml.

+1

ver también System.Security.Cryptography.MD5, System.Security.Cryptography.SHA1, System.Security.Cryptography.SHA256, etc. y revisar la comparación aquí: http://en.wikipedia.org/wiki/Cryptographic_hash_function –

+2

Encoding. El valor predeterminado es la codificación de la página de códigos ANSI actual del sistema operativo. Por lo tanto, su código dará diferentes resultados dependiendo de la configuración en la pestaña Opciones regionales y de idioma - Avanzado. –

+0

wcoenen tiene un punto muy justo. Utilice Encoding.ASCII o Encoding. . –

2

Agregue una referencia .NET a System.Security, y use XmlDsigC14NTransform. Aquí hay un ejemplo ...

/* 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; 
} 
Cuestiones relacionadas