0

I am using following code to generate MD5 Hash for my application it encodes some string value and then I send this generated hash through my web service to some .Net code, that code read my MD5 hash and generate MD5 of the string the strings he is getting from DB and then compare them

public static String getMD5Hash(String val) throws Exception {
        byte[] bytes = val.getBytes();

        MessageDigest m = MessageDigest.getInstance("MD5");
        byte[] digest = m.digest(bytes);
        String hash = new BigInteger(1, digest).toString(16);
        System.out.println(hash.length());
        return hash;
    }

    public static void main(String[] asd) throws Exception{
        for(int i=0;i<10;i++){
            System.out.println(getMD5Hash(i+Math.pow(10, i)+""));//for testing
            System.out.println(getMD5Hash(i+""));//for testing
        }
    }

The issue is as i am getting converted hash from BigInteger and some times generated hash starts with a 0 in that case Biginteger does not consider that 0 and on the other side when .Net generates that hash of the same string it generate it with 0 and in this way string comparison return false, e-g hash code i generate and send "102678D1922799CF9122B3F103975F1" where in .Net hash is "0102678D1922799CF9122B3F103975F1"

also some times it generate code like

.Net generates  0012678D1922799CF9122B3F103975F1 and java 12678D1922799CF9122B3F103975F1 

OR

0002678D1922799CF9122B3F103975F1 and 2678D1922799CF9122B3F103975F1

How can i get this code with all 0s that are in start. Thanks in advance.

NoNaMe
  • 6,020
  • 30
  • 82
  • 110
  • Use apache `Base64` - Reference thread - http://stackoverflow.com/questions/469695/decode-base64-data-in-java – KV Prajapati Nov 02 '12 at 05:23
  • Review this http://stackoverflow.com/questions/415953/generate-md5-hash-in-java – Chuidiang Nov 02 '12 at 05:26
  • client is using same for his .Net application, so i have to use the this one – NoNaMe Nov 02 '12 at 05:26
  • 3
    The length of MD5 is fixed, so you can just pad with zeros. – Thilo Nov 02 '12 at 05:27
  • i have done this padding solution in the application, but looking for a more good way, if there is any – NoNaMe Nov 02 '12 at 05:30
  • 1
    From your question, it sounds like you plan on passing this to another app to "get that string". You aren't planning on using MD5 as a cipher are you? Hash algorithms are a one-way trip. – slashingweapon Nov 02 '12 at 05:35
  • 2
    You can't *decode* something that's been hashed with MD5. As slashingweapon said, hashing is a one-way operation. – FThompson Nov 02 '12 at 05:35
  • Yes you are right that hashing is one-way operation, but on the other end in the service client use to get the string convert it to MD5 hash and then compare with my hash :( – NoNaMe Nov 02 '12 at 05:41

2 Answers2

4

I don't think there's a better way using MessageDigest than just padding the String:

// ...
StringBuilder builder = new StringBuilder();
for (int i = hash.length(); i < 64; i++) {
  builder.append('0');
}
builder.append(hash);
return builder.toString();

...but you can use Guava's Strings.padStart():

// ...
return Strings.padStart(hash, 64, '0');

...or even use Guava's hashing library, which returns the exact same strings as your function (I just checked):

public static String getMD5Hash(String val) throws Exception {
  return Hashing.md5().hashBytes(val.getBytes()).toString();
}
facundofarias
  • 2,973
  • 28
  • 27
Jeff Bowman
  • 90,959
  • 16
  • 217
  • 251
3

This question has some better methods of generating the hex string:

In Java, how do I convert a byte array to a string of hex digits while keeping leading zeros?

Since you're already using BigInteger, this seems like the best solution:

BigInteger bi = new BigInteger(1, digest);
String hash = String.format("%0" + (digest.length << 1) + "X", bi);
Community
  • 1
  • 1
kichik
  • 33,220
  • 7
  • 94
  • 114