MySQL MD5 and Java MD5 not equal
-
06-07-2019 - |
Question
The next function in MySQL
MD5( 'secret' )
generates 5ebe2294ecd0e0f08eab7690d2a6ee69
I would like to have a Java function to generate the same output. But
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();
}
generates
94-190-34-148-236-208-224-240-142-171-118-144-210-166-238-105
Solution
Try encoding in base 16. Just to get you started... 94 in base 16 is 5E.
**Edit:**Try changing your getString method:
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();
}
OTHER TIPS
replace
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 );
This can be shortened to a one-liner by using the utility classes from the Apache Commons Codec library (http://commons.apache.org/codec)
String md = org.apache.commons.codec.digest.DigestUtils.md5hex("whatever");
Those two are equal. The Java one appears to be in decimal. Convert it to hexadecimal.
Consider converting your decimal bytes to hexadecimal. For example 94 base 10 is 5e base 16.
That's because the base is different. The MySQL MD5 result is in base-16, while the Java MD5 is in base-10.
I wish I could help you further, but my math stinks. A friend of mine helped me generate a base-10 checksum from a base-16 checksum in PHP, but I've lost the script. Hope you can find your answer based on this.
String password = org.springframework.util.DigestUtils.md5DigestAsHex("password".getBytes())
System.out.println(password)
Look how I do it, the code is self explainable!
Java code:
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));
}
Output:
MD5: cleartext: 5ab677ec767735cebd67407005786016
Mysql query that produces the same hash:
SELECT md5( 'cleartext' );
Output:
md5('cleartext')
5ab677ec767735cebd67407005786016
Rather than reinventing the wheel, try Apache commons codec (http://commons.apache.org/codec/) which will handle the hex encoding for you with 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;
}
}
Use the utility classes from the Apache Commons Codec library: http://commons.apache.org/codec/
String password = org.apache.commons.codec.digest.DigestUtils.md5Hex("password");
System.out.println(password);