MySQL MD5 и Java MD5 не равны

Следующая функция в MySQL

MD5( 'secret' ) генерирует 5ebe2294ecd0e0f08eab7690d2a6ee69

Я хотел бы, чтобы функция Java генерировала тот же результат. Но

public static String md5( String source ) {
    try {
        MessageDigest md = MessageDigest.getInstance( "MD5" );
        byte[] bytes = md.digest( source.getBytes("UTF-8") );
        return getString( bytes );
    } catch( Exception e )  {
        e.printStackTrace();
        return null;
    }
}

private static String getString( byte[] bytes ) {
    StringBuffer sb = new StringBuffer();
    for( int i=0; i<bytes.length; i++ ) {
        byte b = bytes[ i ];
        sb.append( ( int )( 0x00FF & b ) );
        if( i+1 <bytes.length ) {
            sb.append( "-" );
        }
    }
    return sb.toString();
}

генерирует

94-190-34-148-236-208-224-240-142-171-118-144-210-166-238-105

person Sergio del Amo    schedule 23.06.2009    source источник


Ответы (9)


Попробуйте кодировать в базе 16. Просто для начала... 94 в базе 16 - это 5E.

**Редактировать:** Попробуйте изменить метод getString:

private static String getString( byte[] bytes ) 
{
  StringBuffer sb = new StringBuffer();
  for( int i=0; i<bytes.length; i++ )     
  {
     byte b = bytes[ i ];
     String hex = Integer.toHexString((int) 0x00FF & b);
     if (hex.length() == 1) 
     {
        sb.append("0");
     }
     sb.append( hex );
  }
  return sb.toString();
}
person Randolpho    schedule 23.06.2009
comment
@Randolpho: если b ‹ 0x10, вам нужно добавить 0 - person laalto; 23.06.2009
comment
Отличная точка; отредактировано, чтобы включить проверку @mihi (что лучше IMO, чем проверка значения байта). - person Randolpho; 23.06.2009
comment
вы забыли () в hex.length() - person Sergio del Amo; 23.06.2009
comment
Ах, опасности копирования/вставки. :) Исправлено. - person Randolpho; 23.06.2009

заменять

sb.append( ( int )( 0x00FF & b ) );
if( i+1 <bytes.length ) {
    sb.append( "-" );
}

by

String hex = Integer.toHexString((int) 0x00FF & b);
if (hex.length == 1) sb.append("0");
sb.append( hex );
person mihi    schedule 23.06.2009
comment
Я бы дал вам больше, чем +1, если бы мог. :) - person Randolpho; 23.06.2009

Его можно сократить до однострочного, используя служебные классы из библиотеки кодеков Apache Commons (http://commons.apache.org/codec)

String md = org.apache.commons.codec.digest.DigestUtils.md5hex("whatever");
person stopfstedt    schedule 29.11.2010

Эти двое равны. Java один, кажется, в десятичном формате. Преобразуйте его в шестнадцатеричное.

person Thanatos    schedule 23.06.2009

Потому что база другая. Результат MySQL MD5 находится в базе 16, а Java MD5 — в базе 10.

Я хотел бы помочь вам дальше, но моя математика воняет. Мой друг помог мне сгенерировать контрольную сумму по основанию 10 из контрольной суммы по основанию 16 в PHP, но я потерял скрипт. Надеюсь, вы сможете найти свой ответ на основе этого.

person nikc.org    schedule 23.06.2009

Рассмотрите возможность преобразования десятичных байтов в шестнадцатеричные. Например, 94 по основанию 10 равно 5е по основанию 16.

person laalto    schedule 23.06.2009

Вместо того, чтобы изобретать велосипед, попробуйте кодек Apache commons (http://commons.apache.org/codec/), который будет обрабатывать шестнадцатеричное кодирование для вас с помощью Hex.encodeHex(byte[])

private String encodeAsMD5(String password) {
    try {
        MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] bytes = md.digest(password.getBytes());
        return new String(Hex.encodeHex(bytes));
    } 
    catch(Exception e) {
        e.printStackTrace();
        return null;
    }
}
person James Frost    schedule 09.10.2009

Используйте служебные классы из библиотеки кодеков Apache Commons: http://commons.apache.org/codec

String password = org.apache.commons.codec.digest.DigestUtils.md5Hex("password");
System.out.println(password);
person MauroPorras    schedule 03.01.2011

Посмотрите, как я это делаю, код объясним!

Java-код:

public static void main(String a[]) throws NoSuchAlgorithmException {
    String passClear = "cleartext";
    MessageDigest md5 = MessageDigest.getInstance("MD5"); // you can change it to SHA1 if needed!
    md5.update(passClear.getBytes(), 0, passClear.length());
    System.out.printf("MD5: %s: %s ", passClear, new BigInteger(1, md5.digest()).toString(16));
}

Выход:

MD5: открытый текст: 5ab677ec767735cebd67407005786016

Запрос Mysql, который создает тот же хэш:

SELECT md5( 'cleartext' ); 

Выход:

md5('открытый текст')
5ab677ec767735cebd67407005786016

person Cassio Seffrin    schedule 25.03.2016