MD5
MD5
算法
- 输入:任意长的消息,512 比特长的分组。
- 输出:128 比特的消息摘要
整体流程如下:
-
首先填充原始消息使得对512求余的结果等于448,然后64位记录其长度。
-
512bit一组分为n组。每组中32bit为一段,分为16段
-
对每一组,循环4次下述4轮运算,得到新的A,B,C,D作为下一组的初始值
-
最后得到的A,B,C,D加上第n组原来A,B,C,D的值(即计算前的值)
-
按照地址的顺序从低到高打印对应的A,B,C,D值,就是所求的MD5值。
填充
如果输入信息的长度(bit)对512求余的结果不等于448,就需要填充使得对512求余的结果等于448。填充的方法是填充一个1和n个0。填充完后,信息的长度就为N*512+448(bit)。
然后用64位来存储填充前信息长度。这64位加在第一步结果的后面,这样信息长度就变为N*512+448+64=(N+1)*512位
比如,需要加密消息"gnubd",最后被填充为
小端字节序存储
1 | 67 6E 75 62 64 80 00 00 00 00 00 00 00 00 00 00 |
最后64位(8字节)为0x28(40),消息内容为40位(5字节)。
数据处理
要使A,B,C,D在内存中的显示情况:
1 | A = 0x01234567 |
程序定义应为(小端字节序存储
)
1 | A = 0x67452301; |
每512位(64字节)为1段可以分成n段,(n大于等于1),对于每一段信息(512位,64字节)又划分成16小段(每段32位,4个字节,用M表示)
每一组,经过下列运算处理:
其中Mj表示消息的第j个子段(从0到15)
1 | 第一轮 |
每轮循环后,将A,B,C,D分别加上a,b,c,d,然后进入下一循环,共循环四次。
循环结束后,新的A,B,C,D作为下一组A,B,C,D的初始值,继续进行上述循环运算,得到新的A,B,C,D再加上初始A,B,C,D值。最后按照地址的顺序从低到高打印对应的A,B,C,D值,就是所求的MD5值。
signature
DSL定义如下
后面的3614090360(0xD76AA478),即为相应值转化为十进制后的数。
ROTATE表示移位
1 | private static long F(long x, long y, long z) { |
测试
libcrypto.so.1.1(openssl)
其中和md5有关的函数如下
利用where’s crypto分析
反汇编MD5_Update,主要还是调用了md5_block_data_order
o
md5_block_data_order反汇编后
与signature中对应关系如下
openssl中源代码
1 |
|
md5_local.h
1 |