MD5算法实现疑问:字节序不一致问题
嘿,我懂你在MD5填充这块的纠结——毕竟RFC1321里的比特级规则,刚上手确实容易绕晕。我结合你说的字符串"1"的例子,给你把填充过程拆得明明白白:
首先得把核心规则拎清楚,填充分三步:
- 第一步:在原始消息的比特流末尾追加一个单独的"1"比特(注意是单个比特,不是字节)
- 第二步:继续追加"0"比特,直到整个消息的比特长度模512等于448
- 第三步:追加原始消息的长度(比特数)作为一个64比特的大端序整数
先纠正个小细节:字符串"1"的ASCII码是0x31,对应的二进制比特流是00110001(8比特),不是你写的10001100哦,这个得先掰正,不然后续步骤会乱~
第一步:追加"1"比特
原始消息是8比特的00110001,在末尾加1比特后,整个比特流变成9比特:00110001 1(用空格分开方便看)。
在代码里处理的话,因为我们通常用字节数组存储数据,这一步其实是把原始字节0x31(二进制00110001)的最低位后面补1,转换成字节的话,第一个字节还是0x31,多出来的那个1比特会作为下一个字节的最高位——也就是第二个字节的二进制是10000000(即0x80),剩下的7位先留空等后续补0。
第二步:追加"0"比特凑到448比特
现在当前总比特数是9,我们需要让总长度模512等于448,也就是要补的0比特数是:448 - 9 = 439个。
转换成字节的话:刚才已经用了1个字节存原始数据,1个字节的最高位存了那个追加的1,剩下的7位是0,这就覆盖了7个0比特;还需要补439 -7 = 432个0比特,也就是432 /8 =54个全0字节(0x00)。
这时候总字节数是1 +1 +54 =56,对应的比特数是56*8=448,刚好满足模512等于448的要求。
第三步:追加64比特的原始长度(大端序)
原始消息的长度是8比特("1"是1字节=8比特),我们要把这个长度转换成64比特的大端序整数。
大端序意味着高位字节在前,所以8的64比特表示就是前面60个0比特,后面跟着1000,转换成字节数组就是:[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08]。
把这8个字节加到前面的56字节后面,总长度就变成56+8=64字节=512比特,刚好是MD5处理的一个完整分组。
在代码里处理填充的时候,不用真的去操作单个比特(太麻烦),可以直接按字节来计算:
- 先计算原始消息的字节长度
len,对应的比特长度是len*8 - 计算需要填充的字节数:如果
len %64 <=56,填充字节数是56 - len%64;如果len%64>56,则是64 +56 - len%64 - 填充的第一个字节是
0x80(对应那个追加的1比特,后面跟着7个0),剩下的填充字节都是0x00 - 最后把原始比特长度转换成8字节的大端序数组,追加到填充后的数组末尾
这样处理就和RFC1321的规则完全一致啦,你可以对照自己的代码看看是不是这么实现的~
内容的提问来源于stack exchange,提问作者user8488823

