1

I found a solution to this problem here.

private byte[] toBytes(char[] chars) {
    CharBuffer charBuffer = CharBuffer.wrap(chars);
    ByteBuffer byteBuffer = Charset.forName("UTF-8").encode(charBuffer);
    byte[] bytes = Arrays.copyOfRange(byteBuffer.array(),
            byteBuffer.position(), byteBuffer.limit());
    Arrays.fill(charBuffer.array(), '\u0000'); // clear sensitive data
    Arrays.fill(byteBuffer.array(), (byte) 0); // clear sensitive data
    return bytes;
}

char[] stringChars = "String".toCharArray();
byte[] stringBytes = toBytes(stringChars);

MessageDigest md = MessageDigest.getInstance("MD5");
md.update(stringBytes);
String stringHash = new BigInteger(1, md.digest()).toString(16);

Arrays.fill(stringChars, '\u0000');
Arrays.fill(stringBytes, (byte) 0);

But it seems to have a bug, I can't figure out where or how it happens.

The problem is this part I think:

String hashedPass = new BigInteger(1, md.digest()).toString(16);

The output of above code gives for String:

String = "9a9cce201b492954f0b06abb081d0bb4";
Correct MD5 of above string = "0e67b8eb546c322eeb39153714162ceb",
The code above though gives = "e67b8eb546c322eeb39153714162ceb";

It seems leading zeros of a MD5 are missing.

Community
  • 1
  • 1
M. H.
  • 171
  • 1
  • 14
  • [This answer](http://stackoverflow.com/a/421696/369) suggests simply left-padding with zeros - I don't know if there's a better solution. – Blorgbeard Jan 10 '17 at 02:17
  • @Blorgbeard Thank you very much for linking that post, it seems to have a lot of different (working) solutions for the problem. Is one more secure than another? – M. H. Jan 10 '17 at 02:33
  • 3
    If you're using MD5 for something that needs to be secure, you should switch algorithms. What are you actually doing with these hashes? – Blorgbeard Jan 10 '17 at 02:39
  • Those are mostly stored hashes to communicate between a server via http post, of values just the client and the server know, so they can communicate in a "secure way" without implementing an encryption. I havent found a way yet to implement a https communication. I already changed MessageDigest to SHA1 though, because it's meaningless anyway. – M. H. Jan 10 '17 at 06:31
  • So they're basically used as GUIDs? – Blorgbeard Jan 10 '17 at 18:27

1 Answers1

4

You don't have to use BigInteger for this task, just write a method for converting byte arrays to hex strings.

static String hexEncode(byte [] data) {
    StringBuilder hex = new StringBuilder();
    for (byte b : data) hex.append(String.format("%02x", b));
    return hex.toString();
}

String hash = hexEncode(md.digest());
xiaofeng.li
  • 8,237
  • 2
  • 23
  • 30
  • Thank you very much! I used this now : StringBuffer sb = new StringBuffer(); for (byte b : digest) {sb.append(String.format("%02x", b & 0xff));} This fixes the leading zero problem too. Not sure how to use code in these comments... this is really annoying. – M. H. Jan 10 '17 at 06:28