14

I am using following code block to generate MD5 hashes:

public static String encode(String data) throws Exception {

    /* Check the validity of data */
    if (data == null || data.isEmpty()) {
        throw new IllegalArgumentException("Null value provided for "
                + "MD5 Encoding");
    }

    /* Get the instances for a given digest scheme MD5 or SHA */
    MessageDigest m = MessageDigest.getInstance("MD5");

    /* Generate the digest. Pass in the text as bytes, length to the
     * bytes(offset) to be hashed; for full string pass 0 to text.length()
     */
    m.update(data.getBytes(), 0, data.length());

    /* Get the String representation of hash bytes, create a big integer
     * out of bytes then convert it into hex value (16 as input to
     * toString method)
     */
    String digest = new BigInteger(1, m.digest()).toString(16);

    return digest;
}

When I run the above code segment with String data as [12, B006GQIIEM, MH-ANT2000], the output is a 31 character hash - 268d43a823933c9dafaa4ac0e756d6a.

Is there any problem with the MD5 hash function or there is some problem in the code above?

divinedragon
  • 5,105
  • 13
  • 50
  • 97

4 Answers4

8

The only issue in your code is when MSB is less than Ox10, the result hash string will only have 31 bytes, instead of 32 bytes, missing the leading zero.

Create your md5 string in this way:

            byte messageDigest[] = m.digest();

            hexString = new StringBuffer();
            for (int i=0;i<messageDigest.length;i++) {
                String hex=Integer.toHexString(0xFF & messageDigest[i]);
                if(hex.length()==1)
                    hexString.append('0');

                hexString.append(hex);
            }
rizzz86
  • 3,862
  • 8
  • 35
  • 52
  • So it is just that additional `0`. If the hash length is 31, I need to prefix it with a `0`. That's it right? – divinedragon Nov 16 '12 at 07:47
  • @divinedragon no you doesn't have to add additional '0'. You have to check each character length and append '0' at that particular place. '0' can be added in the middle of the string. You can see in the code that I am checking every string length and appending '0'. – rizzz86 Nov 16 '12 at 07:58
  • 2
    @rizzz86: Sorry, but your comment is misleading because it does not relate to the OP's code but to yours. He used `.toString(16)` and that generates a correct hex representation, *it will not forget to add zeros within the hex string* - it only discards leading zeros. So the OP might as well have prefixed with *as many zeros as are necessary* to get a 32-byte string. – zb226 Jun 19 '13 at 15:45
  • How this code `for(byte b : digest){ sb.append(String.format("%02x", b&0xff)); }` differs from yours...? which one is better ..? – Kanagavelu Sugumar Mar 21 '17 at 16:30
8

You can try this:

...
String digest = String.format("%032x", new BigInteger(1, m.digest()));

Note: it is "%032x", not "%32x".

3

This is how I use MD5 hash. Calculate MD5 hash from string and return 32-byte hexadecimal representation.

import java.io.UnsupportedEncodingException; 
import java.security.MessageDigest; 
import java.security.NoSuchAlgorithmException; 

public class MySimpleMD5 { 

private static String convertToHex(byte[] data) { 
    StringBuffer buf = new StringBuffer();
    for (int i = 0; i < data.length; i++) { 
        int halfbyte = (data[i] >>> 4) & 0x0F;
        int two_halfs = 0;
        do { 
            if ((0 <= halfbyte) && (halfbyte <= 9)) 
                buf.append((char) ('0' + halfbyte));
            else 
                buf.append((char) ('a' + (halfbyte - 10)));
            halfbyte = data[i] & 0x0F;
        } while(two_halfs++ < 1);
    } 
    return buf.toString();
} 

public static String MD5(String text) 
throws NoSuchAlgorithmException, UnsupportedEncodingException  { 
    MessageDigest md;
    md = MessageDigest.getInstance("MD5");
    byte[] md5hash = new byte[32];
    md.update(text.getBytes("iso-8859-1"), 0, text.length());
    md5hash = md.digest();
    return convertToHex(md5hash);
 } 
} 
Yves_T
  • 1,170
  • 2
  • 10
  • 16
0

You can also try this:

private static String getMd5Hash(String input) throws NoSuchAlgorithmException {
    MessageDigest m = MessageDigest.getInstance("MD5");

    byte[] data = m.digest(EncodingUtils.getBytes(input, "UTF8"));

    StringBuilder sBuilder = new StringBuilder();

    for (int i = 0; i < data.length; i++) {

        for (byte b : data) {
            if(b == 0x00){
                sBuilder.append("00");
            } else if ((b & 0x0F) == b) {
                sBuilder.append("0");
                break;
            } else {
                break;
            }
        }

        BigInteger bigInt = new BigInteger(1, data);
        sBuilder.append(bigInt.toString(16));
    }

    // Return the hexadecimal string.
    return sBuilder.toString().substring(0, 32);
}
anTONIos
  • 21
  • 1
  • 3