2010-05-27 23 views
11

Tengo una función que genera un hash MD5 en C# como esto:¿Cómo se puede generar el mismo MD5 Hashcode en C# y Java?

MD5 md5 = new MD5CryptoServiceProvider(); 
byte[] result = md5.ComputeHash(data); 
StringBuilder sb = new StringBuilder(); 
for (int i = 0; i < result.Length; i++) 
{ 
    sb.Append(result[i].ToString("X2")); 
} 
return sb.ToString(); 

en Java mi función es similar a esto:

MessageDigest m = MessageDigest.getInstance("MD5"); 
m.update(bytes,0,bytes.length); 

String hashcode = new BigInteger(1,m.digest()).toString(16); 
return hashcode; 

Mientras que el código C# genera: "02945C9171FBFEF0296D22B0607D522D" los códigos de Java genera: "5a700e63fa29a8eae77ebe0443d59239".

¿Hay alguna manera de generar el mismo hash md5 para el mismo bytearray?

En la demanda:

Este es el testcode en Java:

File file = new File(System.getProperty("user.dir") + "/HashCodeTest.flv"); 
byte[] bytes = null; 
try { 
    bytes = FileUtils.getBytesFromFile(file); 
} catch (IOException e) { 
    fail(); 
} 
try { 
    generatedHashCode = HashCode.generate(bytes); 
} catch (NoSuchAlgorithmException e) { 
    fail(); 
} 

y esto es mi código en C#

var blob = GetBlobByHttpPostedFile(httpPostedFile); 
var hashCode = Md5Factory.ConvertByteArray(blob); 

private static byte[] GetBlobByHttpPostedFile(HttpPostedFile httpPostedFile) 
{ 
    var contentLength = httpPostedFile.ContentLength; 
    var result = new byte[contentLength]; 
    var inputStream = httpPostedFile.InputStream; 
    inputStream.Read(result, 0, contentLength); 

    return result; 
} 

Saludos

+1

Ha publicado el código * de prueba * pero no * datos * de prueba. No cargue desde un archivo o HTTP, solo codifique algunos datos (cualquier dato) en su prueba. –

+0

En particular, acabo de editar mi respuesta con ejemplos de lo que estoy buscando, y aquellos * do * muestran el mismo hash, con un código que es efectivamente el mismo que el suyo. Tenga en cuenta que en su código C# está ignorando el resultado de 'Stream.Read', que nunca es una buena idea ... –

Respuesta

22

Eso debe estar bien - aunque puede hacer que el código Java sea más simple simplemente llamando al

byte[] digest = m.digest(bytes); 

en lugar de llamar al update y luego digest.

¿Está absolutamente seguro tiene los mismos datos en ambos casos? ¿Podría publicar programas de muestra que muestren esta falla con los mismos datos codificados?

EDITAR: Este es el tipo de prueba que estaba pensando. Estos dos programas dan el mismo resultado:

C#:

using System; 
using System.Security.Cryptography; 
using System.Text; 

class Test 
{ 
    static void Main() 
    { 
     byte[] bytes = { 0x35, 0x24, 0x76, 0x12 }; 
     MD5 md5 = new MD5CryptoServiceProvider(); 
     byte[] result = md5.ComputeHash(bytes); 
     StringBuilder sb = new StringBuilder(); 
     for (int i = 0; i < result.Length; i++) 
     { 
      sb.Append(result[i].ToString("x2")); 
     } 
     Console.WriteLine(sb); 
    } 
} 

Java:

import java.math.BigInteger; 
import java.security.MessageDigest; 

public class Test 
{ 
    public static void main(String[] args) throws Exception 
    { 
     byte[] bytes = { 0x35, 0x24, 0x76, 0x12 }; 
     MessageDigest m = MessageDigest.getInstance("MD5"); 
     byte[] digest = m.digest(bytes); 
     String hash = new BigInteger(1, digest).toString(16); 
     System.out.println(hash); 
    } 
} 
+0

genial, no usó BigIneger y obtuvo hash diferente. – misaxi

+0

Al usar esto, pude obtener el mismo hash del código C# y C++. ¡Excelente! –

4

Hola estoy usando el código y funciona

código C#:

public static string ConvertStringToMD5(string ClearText) 
{ 

    byte[] ByteData = Encoding.ASCII.GetBytes(ClearText); 
    //MD5 creating MD5 object. 
    MD5 oMd5 = MD5.Create(); 
    //Hash değerini hesaplayalım. 
    byte[] HashData = oMd5.ComputeHash(ByteData); 

    //convert byte array to hex format 
    StringBuilder oSb = new StringBuilder(); 

    for (int x = 0; x < HashData.Length; x++) 
    { 
     //hexadecimal string value 
     oSb.Append(HashData[x].ToString("x2")); 
    } 

y código Java :

private String getMD5Digest(byte[] buffer) { 
    String resultHash = null; 
    try { 
     MessageDigest md5 = MessageDigest.getInstance("MD5"); 

     byte[] result = new byte[md5.getDigestLength()]; 
     md5.reset(); 
     md5.update(buffer); 
     result = md5.digest(); 

     StringBuffer buf = new StringBuffer(result.length * 2); 

     for (int i = 0; i < result.length; i++) { 
      int intVal = result[i] & 0xff; 
      if (intVal < 0x10) { 
       buf.append("0"); 
      } 
      buf.append(Integer.toHexString(intVal)); 
     } 

     resultHash = buf.toString(); 
    } catch (NoSuchAlgorithmException e) { 
    } 
    return resultHash; 
} 
+0

Tenga en cuenta que si su cadena no está formada completamente por datos ASCII, perderá información ... –

+0

@estergones: ¿Tiene su código equivalente para PHP? – julie

2

Vine a través del problema similar que estábamos usando Java MD5 Hash para determinar si un archivo ha sido procesado. Descubrimos que no podemos crear el mismo hash usando la biblioteca .NET. Probé todas las sugerencias anteriores, lamentablemente no funciona para mí.

La solución que descubrí más tarde es: en lugar de crear una función similar en .NET, llamamos a la función Java directamente en .NET. Hay un gran proyecto de código abierto llamado Ja.NET. Básicamente lo que hice fue: crear una clase Java que crea hash utilizando el mismo código. compilarlo usando Ja.NET javac. Luego, utilizando bam, compilo el archivo de clase Java generado en DLL y lo uso en mi proyecto .NET.

1

Sé que este tema es antiguo, pero me encontré con el mismo problema en este momento y no pude encontrar una respuesta que me funcionara.Estaba escribiendo un parche para un juego y necesitaba el md5hashcode de los archivos como una forma de asegurar que los archivos estuvieran actualizados, pero C# y Java me dieron diferentes cadenas aunque los archivos eran idénticos.

Así es como lo resolví:

C# Código:

public static string getMD5(string fullPath) 
{ 
    MD5 md5 = MD5.Create(); 
    using (FileStream stream = new FileStream(fullPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) 
    { 
     byte[] hash = md5.ComputeHash(stream); 
     StringBuilder sb = new StringBuilder(); 
     for (int j = 0; j < hash.Length; j++) 
     { 
      sb.Append(hash[j].ToString("X2")); 
     } 
     return sb.ToString(); 
    } 
} 

Esto crea una cadena hexadecimal de 32 caracteres. Apache CommonsDigestUtils.md5Hex(InputStream) hace lo mismo, ahora lo único diferente es que el ejemplo de C# devuelve una cadena en mayúscula, por lo que la solución es simplemente convertir el hash del programa Java a una cadena en mayúscula.

código Java:

public static String checkSumApacheCommons(String filePath) 
{ 
    String checksum = null; 
    try 
    { 
     checksum = DigestUtils.md5Hex(new FileInputStream(filePath)); 
    } 
    catch (IOException ex) 
    { 
     ex.printStackTrace(System.out); 
    } 
    return checksum.toUpperCase(); 
} 

Los hashes producidos parecen F674865D8A44695A2443017CFA2B0C67.

Espero que esto ayude a alguien.

Cuestiones relacionadas