攻击方法主要分为猜和查
猜,指穷举法和字典攻击,去猜用户的密码
查,指构建键值对 ((key, value)),根据 (value) 去查 (key)
(1.) 字典攻击
事先制作好密码表,逐一去试,是单纯穷举法的改进
(2.) 明文-哈希索引表
建立大量 ((key, value)) 的键值对,查询时直接对着 (value) 逆向查询 (key)
设哈希密文空间为 ( ho),密文长度为 (n),那么这样的存储空间复杂度为 (O(| ho| n)),查询时间是 (O(1))
虽然查询时间快,但是存储的空间消耗巨大
(3.) 预计算哈希链
(3.1 R) 函数与哈希链
构造 (R) 函数,满足定义域和值域与哈希函数 (H) 相反
考虑简化问题,设密码明文为 (6) 位十进制数,(H) 将其映射为 (8) 位十六进制数,那么 (R) 将哈希过的值映射回 (6) 位十进制数
规定常数 (k),我们选取大量随机明文进行 (k) 次 (H, R) 映射,最终保留链表的首尾 ((h, t)),便可以得到一个哈希链集,上述例子 (k = 2)
一条哈希链包含了多个 ((key, value)) 对,但是我们只存储了首尾 ((h, t)),这在存储空间上的进步非常明显
(3.2) 查询
考虑查询,对密文 (C) 不断做 (R, H) 映射(至多 (k) 次),若得到的结果 (C') 是哈希链集的某条链的尾巴,那么对于这个哈希链,从头往下进行 (H, R) 映射,直到找到明文 (P)
如果做了 (k) 次 (R, H) 映射都没有找到链尾,那么意味着查询失败
对于上述例子,考虑密文 (EEAF1C41),做一次 (R) 运算后得到 (742834),属于哈希链集的某一条链的尾巴,于是从头 (123456) 进行运算,最终找到明文为 (342111)
(3.3) 复杂度
空间复杂度为 (O(frac{| ho|n}{k})),时间复杂度为 (O(k))
(3.4) 哈希链的困境——碰撞
考虑如下两条哈希链
从 ( extbf{123456}) 处发生了碰撞,哈希链剩下所有部分全部碰撞,这样一来,存储的键值对 ((key, value)) 远远低于预期
(4.) 哈希链的改进——彩虹表
(4.1) 彩虹表做的改进——(R) 函数集
彩虹表在哈希链的基础上,采用 (k) 个 (R) 函数,分别记为 (R_{1}, R_{2}, .., R_{k})
这可以保证,两条链碰撞后继续碰撞的概率减小,从而提高了键值对存储的效率
(4.2) 彩虹表的查询
给定密文 (C),假设做 (j) 次 ((R_{i}, H)) 映射找到存储的尾巴
declare ciphertext C, plaintext P
for (j = 1; j <= k; ++j)
for (i = k - j + 1; i <= k; ++i)
P = Ri(C), C = H(P)
if (P is in RainbowTable)
get the plaintext
空间复杂度仍然是 (O(frac{| ho|n}{k})),时间复杂度为 (O(k^2))
(4.3) 防御彩虹表攻击
在计算 (H) 时加入随机 (salt),本质上随机化了哈希函数 (H),但是彩虹表只对确定的 (H) 奏效