Java实现维基百科MD5哈希仅半数结果正确,求问题排查
Java手动实现MD5仅半数结果正确,求排查思路
我正在做一个练习任务,参照维基百科上的MD5哈希算法内容,用Java手动实现MD5,目的是和JDK自带的MD5实现结果做对比。我现在不追求代码最优、最优雅或者最高效,只要能正常运行就行,但目前遇到了一个问题:我的实现只能得到半数正确的结果,完全找不到问题出在哪。以下是我代码的开头片段:
public static String md5DigestHexString(String message) { int[] s = { 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21 }; // 后续的填充、分组、轮次运算等逻辑在这里 }
这种“一半对一半错”的情况在手动实现MD5时真的很常见,大概率是几个细节没处理到位,给你列几个最可能的排查方向:
- 字节序搞反了:MD5的核心运算全程用的是小端字节序,但Java默认是大端。比如你把输入字符串转成字节数组后,分组转换成32位整数的时候,有没有把每个字节的顺序反过来?这一步错了的话,会导致部分输入的哈希结果完全跑偏,少数巧合能蒙对。
- 填充步骤细节出错:MD5要求填充后的总长度是512位的倍数,规则是先加一个
0x80字节,再补一堆0,最后加上原始输入的比特数的64位二进制表示(注意是比特数,不是字节数!),而且这个64位长度也要按小端存储。很多人在这里栽坑,比如用字节数代替比特数,或者没把长度转成小端。 - 轮次运算的对应关系错了:MD5的4轮运算里,每一轮的F类函数(F、G、H、I)、K常量、还有你定义的
s数组里的循环左移次数,必须严格对应。比如某一轮的F函数用成了G,或者左移次数和K常量不匹配,也会导致部分结果错误。 - 初始向量(IV)没设对:MD5的初始IV是
0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476,别搞混顺序或者写错数值,这是运算的起点,错了的话结果肯定不对。
另外,建议你用几个标准测试用例分步验证:
- 先测空字符串:它的MD5是
d41d8cd98f00b204e9800998ecf8427e,能快速验证填充步骤和初始运算是否正确。 - 再测短字符串,比如
"a"的MD5是0cc175b9c0f1b6a831c399e269772661,"abc"的是900150983cd24fb0d6963f7d28e17f72,这些都是公认的标准值,能帮你定位哪一步出问题。
如果方便的话,把你完整的填充、分组运算代码贴出来,这样能更快帮你揪出问题!
内容的提问来源于stack exchange,提问作者Yugo Amaryl
相关产品推荐
相关产品推荐

