Reputation: 18389
I want to compute md5 of any Serilizable object, which is done by following function.
public static String getMd5Hash(Serializable object) {
try {
return getChecksum(object, "MD5");
} catch (Exception e) {
throw new RmsException("Exception while generating md5 hash", e);
}
}
public static String getMd5Hash(Serializable object) {
try {
return getChecksum(object, "MD5");
} catch (Exception e) {
throw new RuntimeException("Exception while generating md5 hash", e);
}
}
private static String getChecksum(Serializable object, String algorithm)
throws IOException, NoSuchAlgorithmException {
try (
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos)
) {
oos.writeObject(object);
MessageDigest md = MessageDigest.getInstance(algorithm);
byte[] theDigest = md.digest(baos.toByteArray());
return DatatypeConverter.printHexBinary(theDigest);
}
}
Test
@Test
public void getMd5Hash() {
String actual = CryptoUtils.getMd5Hash("water");
Assert.assertEquals("9460370bb0ca1c98a779b1bcc6861c2c", actual);
}
OP
Expected :9460370bb0ca1c98a779b1bcc6861c2c (actual md5 for string water)
Actual :37F7DBD142DABF05ACAA6759C4D9E96C (Why the diff?)
Upvotes: 1
Views: 1056
Reputation: 1722
As Terje says,
ObjectOutPutStream adds a header, you can verify that using
public static String getChecksum(Serializable object, String algorithm)
throws IOException, NoSuchAlgorithmException {
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos)) {
oos.writeObject(object);
oos.flush();
MessageDigest md = MessageDigest.getInstance(algorithm);
md.update(object.toString().getBytes());
byte[] theDigest = md.digest();
System.out.println("Without Object output stream="+DatatypeConverter.printHexBinary(theDigest));
md.reset();
System.out.println("object="+object+ " Written to ByteArray is="+baos.toString());
md.update(baos.toByteArray());
theDigest = md.digest();
return DatatypeConverter.printHexBinary(theDigest);
}
}
public static void main(String[] args) throws NoSuchAlgorithmException, IOException {
System.out.println(getChecksum("water", "MD5"));
}
Instead of creating all ByteArrayOutputStream and ObjectOutputStream, you can simple use
md.update(object.toString().getBytes());
To write byte array to MessageDigest.
Thanks
Upvotes: 1
Reputation: 1763
The ObjectOutputStream
adds a header, so the Serializable
you are passing does not actually represent "water" when you get the byte array. Print out baos.toString()
to verify. You can either extend ObjectOutputStream
and override the writeStreamHeader
method, or call md.digest
with the substring of the data, ie md.digest(baos.substring(7).getBytes())
(or something thereabouts). Once the actual data digested is "water", the hash will be correct.
Upvotes: 2