2011-01-25 9 views
11

Estoy tratando de leer un String en el esquema de codificación UTF-16 y realizar hash MD5 en él. Pero, curiosamente, Java y C# están devolviendo resultados diferentes cuando intento hacerlo.Codificación UTF-16 en Java contra C#

La siguiente es la pieza de código en Java:

public static void main(String[] args) { 
    String str = "preparar mantecado con coca cola"; 
    try { 
     MessageDigest digest = MessageDigest.getInstance("MD5"); 
     digest.update(str.getBytes("UTF-16")); 
     byte[] hash = digest.digest(); 
     String output = ""; 
     for(byte b: hash){ 
      output += Integer.toString((b & 0xff) + 0x100, 16).substring(1); 
     } 
     System.out.println(output); 
    } catch (Exception e) { 

    } 
} 

La salida de esto es: 249ece65145dca34ed310445758e5504

La siguiente es la pieza de código en C#:

public static string GetMD5Hash() 
     { 
      string input = "preparar mantecado con coca cola"; 
      System.Security.Cryptography.MD5CryptoServiceProvider x = new System.Security.Cryptography.MD5CryptoServiceProvider(); 
      byte[] bs = System.Text.Encoding.Unicode.GetBytes(input); 
      bs = x.ComputeHash(bs); 
      System.Text.StringBuilder s = new System.Text.StringBuilder(); 
      foreach (byte b in bs) 
      { 
       s.Append(b.ToString("x2").ToLower()); 
      } 
      string output= s.ToString(); 
      Console.WriteLine(output); 
     } 

La salida para esto es: c04d0f518ba2555977fa1ed7f93ae2b3

No estoy seguro, por qué las salidas no son las mismas. ¿Cómo cambiamos el fragmento de código anterior, para que ambos devuelvan el mismo resultado?

+0

Compare primero sus matrices de bytes. Si no coinciden ni siquiera en un solo bit, los hashes son completamente diferentes. Puede haber una lista de materiales o lo que sea en la codificación UTF-16. Puede ser endian pequeño o grande, o lo que sea. – maaartinus

Respuesta

35

UTF-16! = UTF-16.

En Java, getBytes("UTF-16") devuelve una representación big-endian con marca de orden de bytes opcional. C# System.Text.Encoding.Unicode.GetBytes devuelve una representación little-endian. No puedo verificar su código desde aquí, pero creo que deberá especificar la conversión con precisión.

Pruebe getBytes("UTF-16LE") en la versión de Java.

+1

Tiene razón, probé su solución y funciona. – ehsun7b

+2

¡Guau! Muchas gracias, Luther. Esto funciona como magia. – rkg

+0

Vale la pena señalar que si observa la salida en eclipse, todavía no coincide con lo que Visual Studio le muestra. Pero, curiosamente, funciona ... – debracey

5

Lo primero que puedo encontrar, y este podría no ser el único problema, es que C# 's Encoding.Unicode.GetBytes() es littleendian, mientras que el orden de bytes naturales de Java es bigendian.

0

Puede usar System.Text.Enconding.Unicode.GetString(byte[]) para convertir de nuevo a cadena. De esta forma, está seguro de que todo sucede en la codificación Unicode.