彩虹表“只是”预先计算的哈希值表的紧凑表示。在彩虹表的构建过程中,许多可能的输入被尝试和散列。在表构建过程中遇到的每个输入都将被该表成功攻击,而不会被其他攻击。哈希评估集中了大部分建表成本。
所以,基本上,构建一个可以反转N个密码的彩虹表的成本大致相当于通过哈希函数尝试这N个密码的成本——彩虹表的要点是你构建它一次然后就可以使用它破解几个密码。(准确地说,由于建表过程中的链冲突,成本实际上更接近1.7*N,但我们暂时忽略它。)
我曾经对 SHA-1 有过一些经验。使用 SHA-1 的简单密码散列需要处理单个“块”(SHA-1 与 MD5 一样,按 64 字节块处理数据),这需要大约 900 次 32 位逻辑或算术运算。Intel Core2 x86 处理器上的优化实现可以在大约 500 个时钟周期内完成。然而,密码攻击(无论是直接攻击还是彩虹表构建,都无所谓)是一项高度并行的工作,因此可以使用提供 128 位寄存器的 SSE2 指令,其中单个操作码可以执行四个32 位操作同时进行。SSE2 可用的操作种类较少(特别是它不提供轮换,只提供班次),因此操作数上升到 1200 左右;但是,在某些情况下,SSE2 单元会同时执行多个操作码。所以我们最终得到了 800 个时钟周期,用于并行的四个 SHA-1 实例。底线:我的 PC 是 Intel Core2 Q6600,有四个内核,运行频率为 2.4 GHz。每个核心都可以运行我的 SSE2 实现,每秒产生大约4800 万个散列密码。
我还有一块不太小的 Nvidia 显卡,GPU 可以通过CUDA运行任意代码。这是 9800 GTX+,有 128 个内核,运行频率为 1.84 GHz。每个核心每个周期可以执行一个 32 位操作(存在高延迟,但是由于高并行化,可以保持这种每周期一条指令的吞吐量)。内核不知道旋转,因此每个代码将使用每个散列密码 1200 个时钟周期。总性能为每秒1.6 亿个散列密码。
我的电脑和显卡是 2009 年初的,不是顶级的。现在人们可以花几百美元找到一个 GPU,它对密码的哈希处理速度大约是我的 9800 GTX+ 的三倍。所以让我们假设一个拥有普通 PC(成本低于 1000 美元)的攻击者每秒可以散列 50 亿个密码。
以这样的速度,所有 8 个字母数字字符(大小写字母和数字)的密码在大约5 天内完成。一台 1000 美元的电脑。如果你使用 MD5,事情会快 30%(MD5 使用的操作比 SHA-1 少一点)。但是,好的密码散列方案不使用简单的散列调用:它们使用迭代散列,例如 2000 次嵌套散列调用:这将攻击者的成本乘以相同的 2000 因子(因此它将“5 天”变成大约 28年,正如你所说的那样,字面意思是“年龄”)。