在为可序列化对象与字符串计算md5时获得不同的结果

时间:2018-08-07 07:52:17

标签: java md5

我想计算任何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?)

2 个答案:

答案 0 :(得分:2)

ObjectOutputStream添加了标头,因此当您获取字节数组时,您传递的Serializable实际上并不表示“水”。打印baos.toString()进行验证。您可以扩展ObjectOutputStream并覆盖writeStreamHeader方法,也可以使用数据的子字符串(即md.digest(或其附近))调用md.digest(baos.substring(7).getBytes())。一旦提取的实际数据是“水”,哈希就将是正确的。

答案 1 :(得分:1)

如Terje所说,

ObjectOutPutStream添加一个标题,您可以使用

进行验证
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。

谢谢