在计算可序列化对象与字符串的 md5 时得到不同的结果
Getting different results while computing md5 for Serializable object vs string
我想计算任何 Serilizable 对象的 md5,这是通过以下函数完成的。
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
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?)
ObjectOutputStream
增加了一个header,所以你传递的Serializable
实际上并不代表"water",当你得到字节数组的时候。打印出 baos.toString()
来验证。您可以扩展 ObjectOutputStream
并覆盖 writeStreamHeader
方法,或者使用数据的子字符串调用 md.digest
,即 md.digest(baos.substring(7).getBytes())
(或类似的东西)。一旦消化的实际数据是 "water",哈希值将是正确的。
正如 Terje 所说,
ObjectOutPutStream 添加了一个header,你可以验证使用
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"));
}
无需创建所有 ByteArrayOutputStream 和 ObjectOutputStream,您可以简单地使用
md.update(object.toString().getBytes());
将字节数组写入 MessageDigest。
谢谢
我想计算任何 Serilizable 对象的 md5,这是通过以下函数完成的。
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
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?)
ObjectOutputStream
增加了一个header,所以你传递的Serializable
实际上并不代表"water",当你得到字节数组的时候。打印出 baos.toString()
来验证。您可以扩展 ObjectOutputStream
并覆盖 writeStreamHeader
方法,或者使用数据的子字符串调用 md.digest
,即 md.digest(baos.substring(7).getBytes())
(或类似的东西)。一旦消化的实际数据是 "water",哈希值将是正确的。
正如 Terje 所说,
ObjectOutPutStream 添加了一个header,你可以验证使用
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"));
}
无需创建所有 ByteArrayOutputStream 和 ObjectOutputStream,您可以简单地使用
md.update(object.toString().getBytes());
将字节数组写入 MessageDigest。
谢谢