密码知识——MD5长度拓展攻击
知识点
参考【CRYPTO】哈希长度拓展攻击 | 狼组安全团队公开知识库 (wgpsec.org)
填充方法
(补足长度成一个分组,方便hash)
图片摘自:哈希长度拓展攻击(Hash Length Extension Attacks)
当hash函数拿到需要被hash的字符串后,先将其字节长度对64取模。如果余数正好等于56,那么就在该字符串最后添加上8个字节的长度描述符(具体用bit表示)。如果不等于56,就先对字符串进行长度填充,填充时规定第一个字节为hex(80),其余字节均用hex(00)填充,填充至余数为56以后,增加8个字节的长度描述符(该长度描述符为需要被hash的字符串的长度,不是填充之后整个字符串的长度)。
若余数超过56,那么还得再用填充字符\x80\x00……来填充成新的一块,到下一块的第56位停止到加上明文长度的十六进制表达
长度描述符的填入方式
注意MD5运算的时候是小端序存储,假设我们最后8个字节的值为0000001234567890那么存储在MD5运算时的存储方式为9078563412000000,每两个字节构成一个十六进制并且按照逆序的顺序存储。
例子
计算aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbb
60个a和3个b
- 转一下hex
- 填充
那么填充后是下图,填充了57(即64*2-63-8)个填充符(一个\x80
和56个\x00
)
- 加上长度描述符(8位十六进制)
63的十六进制是\x3f,采用小端序存储
md5函数的简略计算过程
参考浅谈HASH长度拓展攻击 - Yunen的博客 - 博客园 (cnblogs.com)
VI向量
一开始有个初始VI
1 | A=0x67452301 |
这串初始向量的值是固定的,作为与第一块数据运算的原始向量。
当这串向量与第一块数据块运算之后,得到了一串新的向量值,这串新的向量值接着与第二块数据块参加运算,直到最后一块数据块。
VI与md5值相转换的过程
“ “ “ 而最后的MD5值就是这最后的向量串经过如下转换的结果。
如向量串:
1 | A=0xab45bc01 |
先两两为一组进行组合,得到如下数据:
1 | ab 45 bc 01 |
再进行高低位互换,得到如下数据:
1 | 01 bc 45 ab |
最终拼接得到MD5值:01bc45ab53bb646afe8aba23627a8446
。 ” ” ”
那么MD5值也可以逆推到VI。
攻击方法
已知前几块的md5,那么我们可以利用这个md5构造一个新的初始VI,然后与我们构造的“填充字块”+任意字符 去计算md5
当然还要跳过省略前面的分组
例子
还是上面那个,我们现在只知道有63个字符,那么已经超过了一个块,那么我们自己帮它填充并加上长度描述符,再在后面添加任意字符,使得这个任意字符单独在一个新的分组中,不干扰前面的MD5计算。
但这里还是有个问题(我也不太清楚):md5函数能自己识别我填充的字符和长度描述符吗?它会不会把我自己加的这些也当成了前面的明文来计算一个新的md5吗。
流程图
例题
笔者解析待续