Apache DigestUtils 似乎计算 MD5 部分错误
Apache DigestUtils seem to calculate MD5 partially wrong
今晚我正在研究一个简单的解决方案,用于在传递流时进行即时 MD5 计算。主要框架立即完美运行。数据流式传输并计算 MD5 哈希。但后来我开始在 3 个不同阶段监控 MD5-Hash。流式传输之前、流式传输期间和流式传输之后。结果让我很吃惊。
最重要的 MD5 摘要显然计算错误。对于所有编码,我使用了与 Apache 的 DigestUtils 相同的方法。但是我没有生成 3 倍相同的输出,而是只有 3 个中的 2 个。
为了验证我的构造中没有一般性错误,我还使用了 Apache 的 (...).binary.Hex
class 来对摘要进行编码。而这一次的结果与其他的相匹配。
流式传输前的 MD5:9065793b048f4efee5ccddb34798ee19
流式传输后的 MD5:9065793b048f4efee5ccddb34798ee19
MD5,同时由 DigestUtils 编码:95d845ff55b5918edc8d1222045dd1cb
流式传输时由 binary.Hex 编码的 MD5:9065793b048f4efee5ccddb34798ee19
这是我非常简单的代码。
第一个class是通过main方法启动的。
它调用 class StreamForwarder 的实例并传递测试字符串
作为输入流。就是这样。
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 将 InputStream 包装在 DigestInputStream 中,并获取 MessageDigest 的实例以在流式传输时计算 MD5 哈希。
它调用 class 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 的预期。
有人能解释一下为什么会这样吗?我是不是做错了什么?
提前致谢!
这一行的问题
String digestUtilsHexString = DigestUtils.md5Hex(digest);
您偶尔会计算摘要的摘要 - md5hex(md5(is))。您可以在bash
中查看
$ echo -n 9065793b048f4efee5ccddb34798ee19 \
| perl -pe 's/([0-9a-f]{2})/chr hex /gie' \
| md5sum
95d845ff55b5918edc8d1222045dd1cb -
今晚我正在研究一个简单的解决方案,用于在传递流时进行即时 MD5 计算。主要框架立即完美运行。数据流式传输并计算 MD5 哈希。但后来我开始在 3 个不同阶段监控 MD5-Hash。流式传输之前、流式传输期间和流式传输之后。结果让我很吃惊。
最重要的 MD5 摘要显然计算错误。对于所有编码,我使用了与 Apache 的 DigestUtils 相同的方法。但是我没有生成 3 倍相同的输出,而是只有 3 个中的 2 个。
为了验证我的构造中没有一般性错误,我还使用了 Apache 的 (...).binary.Hex
class 来对摘要进行编码。而这一次的结果与其他的相匹配。
流式传输前的 MD5:9065793b048f4efee5ccddb34798ee19
流式传输后的 MD5:9065793b048f4efee5ccddb34798ee19
MD5,同时由 DigestUtils 编码:95d845ff55b5918edc8d1222045dd1cb
流式传输时由 binary.Hex 编码的 MD5:9065793b048f4efee5ccddb34798ee19
这是我非常简单的代码。
第一个class是通过main方法启动的。 它调用 class StreamForwarder 的实例并传递测试字符串 作为输入流。就是这样。
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 将 InputStream 包装在 DigestInputStream 中,并获取 MessageDigest 的实例以在流式传输时计算 MD5 哈希。 它调用 class 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 的预期。
有人能解释一下为什么会这样吗?我是不是做错了什么?
提前致谢!
这一行的问题
String digestUtilsHexString = DigestUtils.md5Hex(digest);
您偶尔会计算摘要的摘要 - md5hex(md5(is))。您可以在bash
中查看$ echo -n 9065793b048f4efee5ccddb34798ee19 \
| perl -pe 's/([0-9a-f]{2})/chr hex /gie' \
| md5sum
95d845ff55b5918edc8d1222045dd1cb -