Jean-Philippe Roy
Jean-Philippe Roy

Reputation: 4812

MD5 Bizarre Behavior on Android

I have a simple method that takes in a String and hashes it with the MD5 algorithm (needless to say that all these sysos are for monitoring/debugging the weird behaviors I've been experiencing) :

private String hashMD5(String input) throws UnsupportedEncodingException, NoSuchAlgorithmException {
    MessageDigest digest = MessageDigest.getInstance("MD5");

    // BYTES_ENCODING == "UTF-8"
    digest.update(input.getBytes(BYTES_ENCODING), 0, input.length());

    System.out.println(new BigInteger(1, digest.digest()).toString(16));
    System.out.println(new BigInteger(1, digest.digest()).toString(16));
    System.out.println(new BigInteger(1, digest.digest()).toString(16));

    String hash = new BigInteger(1, digest.digest()).toString(16);
    System.out.println(hash + " : used hash");
    System.out.println(hash.length() + " - " + new BigInteger(1, digest.digest()).toString(16).length());
    return hash;
}

When calling this method with a set String, here's what I get:

02-18 08:49:23.355: I/System.out(2753): 78bfa0ce6d53a698a98aac899562bb4
02-18 08:49:23.355: I/System.out(2753): d41d8cd98f00b204e9800998ecf8427e
02-18 08:49:23.355: I/System.out(2753): d41d8cd98f00b204e9800998ecf8427e
02-18 08:49:23.355: I/System.out(2753): d41d8cd98f00b204e9800998ecf8427e : used hash
02-18 08:49:23.355: I/System.out(2753): 32 - 32

So my question to you all is:

Why would the first BigInteger be any different from all of the other ones (in length and in content) ?

I'm experiencing this same behavior on both of my testing devices, where I must create at least 2 BigInteger to get a hash of the right length:

  1. Nexus S (Android 4.1.1)
  2. Nexus 7 (Android 4.2.2)

Upvotes: 0

Views: 151

Answers (1)

Javier
Javier

Reputation: 12398

Because the first digest.update() updates the digest but do not reset the MessageDigest instence. Then the first result that is printed is the hash of input.getBytes(BYTES_ENCODING), 0, input.length()) concatenated with new BigInteger(1, digest.digest()).toString(16)

Comment the line that reads digest.update(...)

Note that BigInteger.toString() does only convert a byte array to hexadecimal. It does not append any leading zero.

String s = new BigInteger(1, digest.digest()).toString(16);
while (s.length()<16) s="0"+s; //or something else to the same effect
System.out.println(s);

Upvotes: 2

Related Questions