Apache DigestUtils似乎计算MD5部分错误

时间:2016-08-23 20:46:56

标签: java hash md5

今晚我正在研究一种简单的解决方案,用于在传递流的情况下进行动态MD5计算。主要框架完全正确地运作。数据流式传输并计算MD5哈希值。但后来我开始在3个不同的阶段监测MD5-Hash。在流媒体之前,流媒体和流媒体之后。我对结果感到惊讶。

最重要的MD5消化显然是错误计算的。对于所有编码,我使用了与Apache的DigestUtils相同的方法。但是,不是产生相同输出的3倍,而是只有3个中的2个。

要验证我的构造中没有一般错误,我还使用了Apache的(...).binary.Hex类来编码摘要。而这次结果与其他结果相匹配。

流式传输前的MD5:9065793b048f4efee5ccddb34798ee19

流式传输后的MD5:9065793b048f4efee5ccddb34798ee19

由DigestUtils编码的流式传输时的MD5: 95d845ff55b5918edc8d1222045dd1cb

MD5在流媒体编码时由binary.Hex:9065793b048f4efee5ccddb34798ee19

这是我非常简单的代码。

第一个类是通过main方法启动的。 它调用StreamForwarder类的实例并传递测试字符串 作为InputStream。那就是它。

import java.io.ByteArrayInputStream;
import java.io.InputStream;

import org.apache.commons.codec.digest.DigestUtils;

public class StreamProvider {
    private static final byte[] streamContent;

    static {
        streamContent = "i9BjYXhrIA7FvuQ8WTIhIbgCGwfIGKfu".getBytes();
    }

    private static InputStream getStreamContent() {
        return new ByteArrayInputStream(streamContent);
    }

    public static void main(String args[]) {
        System.out.println("MD5 before streaming: " + 
            DigestUtils.md5Hex(streamContent));

        StreamForwarder streamForwarder = new StreamForwarder();
        streamForwarder.forwardStream(getStreamContent());
    }
}

StreamForwarder在DigestInputStream中包装InputStream,并获取MessageDigest的实例以在流式传输时计算MD5哈希值。 它调用StreamConsumer类的实例并传递DigestInputStream。

import java.io.InputStream;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.digest.DigestUtils;

public class StreamForwarder {

    public void forwardStream(InputStream is) throws NoSuchAlgorithmException {
        MessageDigest md = MessageDigest.getInstance("MD5");
        DigestInputStream dis = new DigestInputStream(is, md);

        StreamConsumer streamConsumer = new StreamConsumer();
        streamConsumer.printStreamContent(dis);

        byte digest[] = md.digest();

        String digestUtilsHexString = DigestUtils.md5Hex(digest);
        String binaryHexString = new String(Hex.encodeHex(digest));

        System.out.println("MD5 while streaming encoded by DigestUtils: " + 
            digestUtilsHexString);
        System.out.println("MD5 while streaming encoded by binary.Hex: " + 
            binaryHexString);
    }
}

最后,StreamConsumer使用Apache的IOUtils读取流。

import java.io.IOException;
import java.io.InputStream;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.IOUtils;

public class StreamConsumer {

    public void printStreamContent(InputStream is) throws IOException {
        String myString = IOUtils.toString(is, "UTF-8");

        System.out.println("MD5 after streaming: " + 
            DigestUtils.md5Hex(myString.getBytes()));
    }
}

正如你所看到的,背后没有火箭科学。但是StreamForwarder.class的输出仍然不是我对DigestUtils的编码HexString所期望的。

有人向我解释为什么会这样吗?我做错了什么?

提前致谢!

1 个答案:

答案 0 :(得分:3)

此行中的问题

String digestUtilsHexString = DigestUtils.md5Hex(digest);

您偶尔会计算摘要的摘要 - md5hex(md5(is))。你可以用bash检查它

$ echo -n 9065793b048f4efee5ccddb34798ee19 \
    | perl -pe 's/([0-9a-f]{2})/chr hex $1/gie' \
    | md5sum
95d845ff55b5918edc8d1222045dd1cb  -