繁体   English   中英

在为可序列化对象与字符串计算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添加一个标头,因此当您获取字节数组时,您传递的Serializable实际上并不表示“水”。 打印出baos.toString()进行验证。 您可以扩展ObjectOutputStream并重写writeStreamHeader方法,也md.digest使用数据的子字符串(即md.digest(baos.substring(7).getBytes()) (或其附近))调用md.digest 一旦提取的实际数据是“水”,则哈希将是正确的。

正如特耶所说

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。

谢谢

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM