JAVA Md5 возвращает недетерминированные результаты

Я написал следующую функцию для вычисления контрольной суммы Md5 в Java.

class Utils {
 public static String md5Hash(String input) {
        String result = "";
        try {
            System.out.println("Input=" + input);
            final MessageDigest md = MessageDigest.getInstance("MD5");
            md.reset();
            md.update(input.getBytes());
            result = md.digest().toString();
        } catch (Exception ee) {
            System.err.println("Error computing MD5 Hash");
        }
        return result;
    }
};

Многократный вызов Utils.md5Hash("abcde") дает разные результаты. Насколько я понимаю, md5 возвращает детерминированную и уникальную контрольную сумму для строки. Это неправильно? В противном случае, пожалуйста, дайте мне знать об ошибке в моей реализации. Спасибо


person workwise    schedule 17.09.2012    source источник
comment
Дублировать stackoverflow.com/questions/415953/generate-md5- хеш-в-java   -  person Endy    schedule 17.09.2012
comment
Не совсем дубликат. Я реализовал эту функцию и хотел помочь с ошибкой. Тот попросил реализовать с нуля.   -  person workwise    schedule 17.09.2012
comment
@workwise, так что вам не нужна реализация «с нуля»? В таком случае, почему вы не используете общий дайджест библиотеки Apache? Класс org.apache.commons.codec.digest.DigestUtils имеет хорошую реализацию функции varios range md5*.   -  person user1516873    schedule 17.09.2012


Ответы (3)


Метод toString() массива байтов не возвращает осмысленной строки. Он возвращает тип объекта массива, за которым следует хэш-код массива.

Преобразуйте массив байтов в строку, используя кодировку Hex или Base64, если вы хотите, чтобы он был напечатан. У Apache commons-codec есть методы для этого.

Кроме того, обязательно укажите кодировку en, которая поддерживает любой тип символов для преобразования вашей строки в массив байтов. Используемый вами метод использует кодировку платформы по умолчанию, что может привести к сбою, если, например, это латиница-1, а вы преобразуете символы, отличные от латиницы-1. UTF-8 - хороший выбор.

person JB Nizet    schedule 17.09.2012
comment
Также укажите кодировку при вызове input.getBytes(), иначе она может различаться в разных системах с разными кодировками по умолчанию. - person Jon Skeet; 17.09.2012
comment
+1 Вместо этого вы можете использовать result = Arrays.toString(md.digest());, хотя это не очень компактно и не используется широко. - person Peter Lawrey; 17.09.2012
comment
@JonSkeet: я редактировал свой ответ, пока вы писали свой комментарий :-) - person JB Nizet; 17.09.2012

Я сделал, используя следующий способ:

 public static String encryptedLoginPassword( String password ) 
    {
        String encryptedData="";
    try{
        MessageDigest algorithm = MessageDigest.getInstance("MD5");
        byte[] defaultBytes = password.getBytes();
        algorithm.reset();
        algorithm.update(defaultBytes);
        byte messageDigest[] = algorithm.digest();

        StringBuffer hexString = new StringBuffer();
        for (int i=0;i<messageDigest.length;i++) {
            hexString.append(Integer.toHexString(0xFF & messageDigest[i]));
        }
        encryptedData=hexString.toString();
    }catch(NoSuchAlgorithmException nsae){

    }
    return encryptedData;
    }
person Dinup Kandel    schedule 17.09.2012

в коде, данном Динупом Канделем, мне пришлось изменить это:

for (int i=0;i<messageDigest.length;i++) {
   hexString.append(Integer.toHexString(0xFF & messageDigest[i]));
}

in to

 if ((0xff & messageDigest[i]) < 0x10) {
     hexString.append("0"
     + Integer.toHexString((0xFF & messageDigest[i])));
 } else {
     hexString.append(Integer.toHexString(0xFF & messageDigest[i]));
 }

чтобы мои модульные тесты работали.

примечание: я использовал это, чтобы проверить правильный ответ:

echo -n MyTestString | md5sum
person michel.iamit    schedule 24.12.2015