MySQL的MD5和Java的MD5不相等。

10

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
10个回答

25

尝试使用十六进制进行编码。只是为了让你开始... 94在十六进制中是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();
}

@Randolpho:如果 b 小于 0x10,则需要用 0 填充。 - laalto
优秀的观点;编辑包括@mihi的检查(在我看来比字节值检查更好)。 - Randolpho
你忘记在hex.length()中加上()了。 - Sergio del Amo
啊,复制/粘贴的危险。:) 已修复。 - Randolpho

6

替换

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

如果可以的话,我会给你更多的赞。 :) - Randolpho

4
这可以通过使用 Apache Commons Codec 库的实用程序类来简化为一行代码 (http://commons.apache.org/codec)。
String md = org.apache.commons.codec.digest.DigestUtils.md5hex("whatever");

3

这两个值是相等的。Java中的值看起来是十进制的。将其转换为十六进制。


3

这是因为基数不同。MySQL的MD5结果是在16进制中,而Java的MD5是在10进制中。

我希望我能帮你更多,但我的数学很糟糕。我的一个朋友曾经帮我在PHP中从16进制的校验和生成了一个10进制的校验和,但我已经丢失了这个脚本。希望你可以根据这个找到你的答案。


2
String password = org.springframework.util.DigestUtils.md5DigestAsHex("password".getBytes())
System.out.println(password)

2

考虑将十进制字节转换为十六进制。例如,10进制的94可以转换为16进制的5e。


1
不必重复发明轮子,可以尝试使用Apache Commons Codec(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;
    }
}

0

使用来自Apache Commons Codec库的实用类:http://commons.apache.org/codec/

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

0

看我怎么做,代码是自解释的!

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('cleartext')
5ab677ec767735cebd67407005786016


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接