Как вы можете генерировать один и тот же хэш-код MD5 в C # и Java? - PullRequest
13 голосов
/ 27 мая 2010

У меня есть функция, которая генерирует хеш MD5 в C #, например:

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();

В Java моя функция выглядит так:

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

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

В то время как код C # генерирует: «02945C9171FBFEF0296D22B0607D522D», коды Java генерируют: «5a700e63fa29a8eae77ebe0443d59239».

Есть ли способ сгенерировать тот же хэш md5 для того же байтового массива?

По запросу:

Это тестовый код в 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();
}

и это мой код в 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;
}

Приветствия

Ответы [ 4 ]

24 голосов
/ 27 мая 2010

Это должно быть хорошо - хотя вы могли бы упростить код Java, просто вызвав

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

вместо вызова update, затем digest.

Вы абсолютно уверены, у вас есть одинаковые данные в обоих случаях? Не могли бы вы опубликовать примеры программ, показывающих этот сбой с теми же жестко закодированными данными?

РЕДАКТИРОВАТЬ: Вот такой тест, о котором я думал. Эти две программы дают одинаковый результат:

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);
    }
}
4 голосов
/ 27 мая 2010

Привет, я использую этот код, и он работает

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

и код 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;
}
2 голосов
/ 06 октября 2011

Я столкнулся с аналогичной проблемой, которую мы использовали Java MD5 Hash, чтобы определить, был ли обработан файл. Мы обнаружили, что не можем создать такой же хеш с помощью библиотеки .NET. Я попробовал все вышеизложенное предложение, к сожалению, оно не работает для меня.

Решение, которое я обнаружил позже: вместо создания аналогичной функции в .NET мы вызываем функцию Java непосредственно в .NET. Существует один отличный проект с открытым исходным кодом, который называется Ja.NET. По сути, я сделал: создать класс Java, который создает хэш, используя тот же код. скомпилируйте его, используя Ja.NET javac. Затем с помощью bam скомпилируйте сгенерированный файл классов Java в DLL и используйте его в моем проекте .NET.

1 голос
/ 25 января 2014

Я знаю, что эта тема старая, но я столкнулся с той же проблемой только сейчас и не смог найти ответ, который работал для меня. Я писал патчер для игры, и мне нужно было md5 hashcode файлов, чтобы гарантировать, что файлы обновлены, но C # и Java дали мне разные строки, хотя файлы были идентичны.

Вот как я это решил:

C # Код:

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

Это создает шестнадцатеричную строку из 32 символов. Apache Commons DigestUtils.md5Hex(InputStream) делает то же самое, теперь единственное отличие состоит в том, что пример C # возвращает строку в верхнем регистре, поэтому решение заключается в простом преобразовании хэша из программы Java в строку в верхнем регистре. *

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

Полученные хэши выглядят как F674865D8A44695A2443017CFA2B0C67.

Надеюсь, это кому-нибудь поможет.

...