0

I am getting an error while trying to check the MD5 hash of a file.

The file, notice.txt has the following contents:

My name is sanjay yadav . i am in btech computer science .>>

When I checked online with onlineMD5.com it gave the MD5 as: 90F450C33FAC09630D344CBA9BF80471.

My program output is:

My name is sanjay yadav . i am in btech computer science .
Read 58 bytes
d41d8cd98f00b204e9800998ecf8427e

Here's my code:

import java.io.*;
import java.math.BigInteger;
import java.security.DigestException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class MsgDgt {
    public static void main(String[] args) throws IOException, DigestException, NoSuchAlgorithmException {

        FileInputStream inputstream = null;
        byte[] mybyte = new byte[1024];

        inputstream = new FileInputStream("e://notice.txt");
        int total = 0;
        int nRead = 0;
        MessageDigest md = MessageDigest.getInstance("MD5");
        while ((nRead = inputstream.read(mybyte)) != -1) {
            System.out.println(new String(mybyte));
            total += nRead;
            md.update(mybyte, 0, nRead);
        }

        System.out.println("Read " + total + " bytes");
        md.digest();
        System.out.println(new BigInteger(1, md.digest()).toString(16));
    }
}
Jason Sundram
  • 12,225
  • 19
  • 71
  • 86
Bitopan
  • 53
  • 1
  • 1
  • 10
  • possible duplicate of [Getting a File's MD5 Checksum in Java](http://stackoverflow.com/questions/304268/getting-a-files-md5-checksum-in-java) – Simon Jul 02 '13 at 06:07
  • I will not rely on that website now..i think the output 2f4c6a40682161e5b01c24d5aa896da0 is correct... you missed one zero in the last..(please Check it). The Content Was "My name is sanjay yadav . i am in btech computer science ." – Bitopan Jul 02 '13 at 07:14

2 Answers2

1

There's a bug in your code and I believe the online tool is giving the wrong answer. Here, you're currently computing the digest twice:

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

Each time you call digest(), it resets the internal state. You should remove the first call to digest(). That then leaves you with this as the digest:

2f4c6a40682161e5b01c24d5aa896da0

That's the same result I get from C#, and I believe it to be correct. I don't know why the online checker is giving an incorrect result. (If you put it into the text part of the same site, it gives the right result.)

A couple of other points on your code though:

  • You're currently using the platform default encoding when converting the bytes to a string. I would strongly discourage you from doing that.
  • You're currently converting the whole buffer to a string, instead of only the bit you've read.
  • I don't like using BigInteger as a way of converting binary data to hex. You potentially need to pad it with 0s, and it's basically not what the class was designed for. Use a dedicated hex conversion class, e.g. from Apache Commons Codec (or various Stack Overflow answers which provide standalone classes for the purpose).
  • You're not closing your input stream. You should do so in a finally block, or using a try-with-resources statement in Java 7.
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • I will not rely on that website now..i think the output 2f4c6a40682161e5b01c24d5aa896da0 is correct... you missed one zero in the last..(please Check it). The Content Was "My name is sanjay yadav . i am in btech computer science ." – Bitopan Jul 02 '13 at 07:04
0

I use this function:

public static String md5Hash(File file) {
    try {
        MessageDigest md = MessageDigest.getInstance("MD5");
        InputStream is = new FileInputStream(file);
        byte[] buffer = new byte[1024];

        try {
            is = new DigestInputStream(is, md);

            while (is.read(buffer) != -1) { }
        } finally {
            is.close();
        }

        byte[] digest = md.digest();

        BigInteger bigInt = new BigInteger(1, digest);
        String output = bigInt.toString(16);
        while (output.length() < 32) {
            output = "0" + output;
        }

        return output;
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

    return null;
}
Knossos
  • 15,802
  • 10
  • 54
  • 91
  • Why would you want to create a new byte array for each `read` call? It seems a little tortuous to me - as is using `BigInteger` for hex conversions (rather than code which is designed to convert a byte array to hex). The exception handling is worrying, too... – Jon Skeet Jul 02 '13 at 06:09
  • Actually, I am not sure about the whole function now to think about it. This was an example I found online. Although, I am not certain the problem with using BigInteger, what would you do instead? I completely agree with the byte array declaration. – Knossos Jul 02 '13 at 06:18
  • I'd either use something like Apache Commons Codec, or find an answer to one of the many "how do I convert bytes to hex" questions on Stack Overflow. – Jon Skeet Jul 02 '13 at 06:21
  • I will not rely on that website now..i think the output 2f4c6a40682161e5b01c24d5aa896da0 is correct... you missed one zero in the last..(please Check it). The Content Was "My name is sanjay yadav . i am in btech computer science ." – Bitopan Jul 02 '13 at 07:16