Get MD5 String from Message Digest
Asked Answered
M

11

38

I understand how it works but if I want to print out the MD5 as String how would I do that?

public static void getMD5(String fileName) throws Exception{
    InputStream input =  new FileInputStream(fileName);
    byte[] buffer = new byte[1024];

    MessageDigest hash = MessageDigest.getInstance("MD5");
    int read;
    do {
        read = input.read(buffer);
        if (read > 0) {
            hash.update(buffer, 0, read);
        }
    } while (read != -1);
    input.close();
}
Moisesmoishe answered 29/3, 2011 at 9:11 Comment(0)
L
23

Try this

StringBuffer hexString = new StringBuffer();
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] hash = md.digest();

for (int i = 0; i < hash.length; i++) {
    if ((0xff & hash[i]) < 0x10) {
        hexString.append("0"
                + Integer.toHexString((0xFF & hash[i])));
    } else {
        hexString.append(Integer.toHexString(0xFF & hash[i]));
    }
}
Landsturm answered 29/3, 2011 at 9:15 Comment(1)
Note also that StringBuilder can be now used instead of StringBuffer, cons and pros of each are discussed in this question: #355589Astaire
Q
80

You can get it writing less:

String hex = (new HexBinaryAdapter()).marshal(md5.digest(YOUR_STRING.getBytes()))
Question answered 20/9, 2012 at 14:6 Comment(3)
Do you know if there are any performance considerations here? Assuming we reused a single HexBinaryAdapter, would this introduce any significant overheads compared to doing the bit operations ourselves? We need to use this code a lot as we use the MD5 for URLs as the key into our image cache.Mefford
Java's source is public. :) HexBinaryAdapter.marshal() only calls DatatypeConverter.printHexBinary() (you can actually use that instead, if you want to avoid instantiating a HexBinaryAdapter), which in turn instantiates a singleton DatatypeConverterImpl the first time it's called. After that, it's just a straight call to DatatypeConverterImpl's printHexBinary. It uses a method pretty similar to WhiteFang34's answer.Bromoform
HexBinaryAdapter is not in JDK9Veranda
V
29
    String input = "168";
    MessageDigest md = MessageDigest.getInstance("MD5");
    byte[] md5sum = md.digest(input.getBytes());
    String output = String.format("%032X", new BigInteger(1, md5sum));

or

DatatypeConverter.printHexBinary( MessageDigest.getInstance("MD5").digest("a".getBytes("UTF-8")))
Varix answered 29/3, 2011 at 9:16 Comment(4)
DatatypeConverter is not in JDK9Veranda
@Veranda See #43574926Varix
yah I was just looking at that temporary hack for a lib, but for this question answers that do not depend on deprecated code are better.Veranda
BigInteger seems to have an issue when the leading hex digit is 0.Disorient
L
23

Try this

StringBuffer hexString = new StringBuffer();
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] hash = md.digest();

for (int i = 0; i < hash.length; i++) {
    if ((0xff & hash[i]) < 0x10) {
        hexString.append("0"
                + Integer.toHexString((0xFF & hash[i])));
    } else {
        hexString.append(Integer.toHexString(0xFF & hash[i]));
    }
}
Landsturm answered 29/3, 2011 at 9:15 Comment(1)
Note also that StringBuilder can be now used instead of StringBuffer, cons and pros of each are discussed in this question: #355589Astaire
C
23

You can also use Apache Commons Codec library. This library includes methods public static String md5Hex(InputStream data) and public static String md5Hex(byte[] data) in the DigestUtils class. No need to invent this yourself ;)

Chariot answered 29/3, 2011 at 9:20 Comment(0)
B
9

First you need to get the byte[] output of the MessageDigest:

byte[] bytes = hash.digest();

You can't easily print this though (with e.g. new String(bytes)) because it's going to contain binary that won't have good output representations. You can convert it to hex for display like this however:

StringBuilder sb = new StringBuilder(2 * bytes.length);
for (byte b : bytes) {
    sb.append("0123456789ABCDEF".charAt((b & 0xF0) >> 4));
    sb.append("0123456789ABCDEF".charAt((b & 0x0F)));
}
String hex = sb.toString();
Bruise answered 29/3, 2011 at 9:15 Comment(2)
Thanks for mentioning the actual problem, and what would come as a first thought in byte-string which is to just use the string constructor. Also, I'm surprised no one suggested Base64. How does Base64 compare to these HexToBinary answers.Caligula
Found this: https://mcmap.net/q/216483/-base64-vs-hex-for-sending-binary-content-over-the-internet-in-xml-docCaligula
C
7

Shortest way:

String toMD5(String input) {
    MessageDigest md = MessageDigest.getInstance("MD5");
    byte[] raw = md.digest(input.getBytes());
    return DatatypeConverter.printHexBinary(raw);
}

Just remember to handle the exception.

Claudetta answered 16/12, 2018 at 18:23 Comment(0)
F
4

With the byte array, result from message digest:

...
byte hashgerado[] = md.digest(entrada);
...

for(byte b : hashgerado)
    System.out.printf("%02x", Byte.toUnsignedInt(b));

Result (for example):
89e8a9f68ad3c4bba9b9d3581cf5201d

Frulla answered 20/5, 2016 at 4:28 Comment(0)
I
2
/**
 * hashes:
 * e7cfa2be5969e235138356a54bad7fc4
 * 3c9ec110aa171b57bb41fc761130822c
 *
 * compiled with java 8 - 12 Dec 2015
 */
public static String generateHash() {
    long r = new java.util.Random().nextLong();
    String input = String.valueOf(r);
    String md5 = null;

    try {
        java.security.MessageDigest digest = java.security.MessageDigest.getInstance("MD5");
        //Update input string in message digest
        digest.update(input.getBytes(), 0, input.length());
        //Converts message digest value in base 16 (hex)
        md5 = new java.math.BigInteger(1, digest.digest()).toString(16);
    }
    catch (java.security.NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
    return md5;
}
Incommunicative answered 10/12, 2015 at 19:35 Comment(0)
T
2

FYI...

In certain situations this did not work for me

md5 = new java.math.BigInteger(1, digest.digest()).toString(16);

but this did

StringBuilder sb = new StringBuilder();

for (int i = 0; i < digest.length; i++) {
    if ((0xff & digest[i]) < 0x10) {
        sb.append("0").append(Integer.toHexString((0xFF & digest[i])));
    } else {
        sb.append(Integer.toHexString(0xFF & digest[i]));
    }
}

String result = sb.toString();
Twodimensional answered 27/2, 2016 at 0:32 Comment(1)
Welcome to Stack Overflow, @WillBerger ! While this code may answer the question, providing additional context regarding how and/or why it solves the problem would improve the answer's long-term value.Verona
B
-1

Call hash.digest() to finish the process. It will return an array of bytes.

You can create a String from a byte[] using a String constructor, however if you want a hex string you'll have to loop through the byte array manually and work out the characters.

Beem answered 29/3, 2011 at 9:14 Comment(0)
V
-2

This is another version of @anything answer:

StringBuilder sb = new StringBuilder();

for (int i = 0; i < digest.length; i++) {
    if ((0xff & digest[i]) < 0x10) {
        sb.append("0").append(Integer.toHexString((0xFF & digest[i])));
    } else {
        sb.append(Integer.toHexString(0xFF & digest[i]));
    }
}

String result = sb.toString();
Voltage answered 14/11, 2014 at 14:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.