SHA-1 哈希算法的碰撞攻击原理与实例分析
我将为你详细讲解SHA-1哈希算法中碰撞攻击的原理,并通过一个著名的实例来具体分析。这个讲解将分为四个主要部分:先回顾SHA-1的基本知识,然后介绍碰撞攻击的核心思想,接着讲解针对SHA-1的实际攻击技术,最后分析一个具体的碰撞实例。
第一部分:SHA-1算法快速回顾
在理解碰撞攻击之前,我们需要先了解SHA-1算法的基本流程。SHA-1(安全哈希算法1)是一个输出为160位(20字节)哈希值的密码哈希函数,其处理过程可总结为以下几个步骤:
-
消息填充
- 在原始消息后添加一个比特“1”。
- 填充若干个“0”,直到消息长度对512取模等于448。
- 在最后64位中写入原始消息的长度(以比特为单位)。
-
初始化哈希值(H⁽⁰⁾)
SHA-1使用5个32位(共160位)的寄存器(A, B, C, D, E)来保存中间哈希值,初始值为:A = 0x67452301 B = 0xEFCDAB89 C = 0x98BADCFE D = 0x10325476 E = 0xC3D2E1F0 -
处理消息分组(80轮压缩)
每个512位的消息分组会被扩展为80个32位字(W₀ ~ W₇₉),然后进行80轮迭代运算。这80轮分为4个阶段,每20轮使用一个不同的非线性函数fₜ和常量Kₜ:- 第0-19轮:f₁(B, C, D) = (B ∧ C) ∨ (¬B ∧ D), K₁ = 0x5A827999
- 第20-39轮:f₂(B, C, D) = B ⊕ C ⊕ D, K₂ = 0x6ED9EBA1
- 第40-59轮:f₃(B, C, D) = (B ∧ C) ∨ (B ∧ D) ∨ (C ∧ D), K₃ = 0x8F1BBCDC
- 第60-79轮:f₄(B, C, D) = B ⊕ C ⊕ D, K₄ = 0xCA62C1D6
每一轮的核心计算是:
TEMP = (A循环左移5位) + fₜ(B, C, D) + E + Wₜ + Kₜ E = D D = C C = B循环左移30位 B = A A = TEMP -
输出哈希值
处理完所有分组后,最终的A, B, C, D, E连接起来,就是160位的SHA-1哈希值。
第二部分:哈希碰撞攻击的基本原理
碰撞攻击的目标是找到两个不同的输入消息M和M',使得它们的哈希值H(M) = H(M')完全相同。对于理想的160位哈希函数,找到一个碰撞平均需要尝试约2⁸⁰次(生日攻击原理)。但SHA-1的设计弱点使得攻击者可以用远低于2⁸⁰的计算量找到碰撞。
攻击的核心思路是差分分析:
- 构造差分路径:首先寻找一个特定的“输入消息差异”∆M(即M和M'在某些比特位上的差异模式),使得这个差异经过SHA-1的多轮压缩后,最终在输出端能够“相互抵消”,产生零差异(即相同哈希值)。
- 满足差分条件:消息差异在SHA-1的每轮传播中,会引入一系列必须满足的“条件”。这些条件通常表现为中间寄存器(A, B, C, D, E)的某些比特位必须为0或1。攻击者需要通过修改消息中可控的部分(如填充区域、IV等)来满足这些条件。
- 消息修改技术:在早期轮次中,攻击者可以自由调整消息,以高效满足条件。对于后续更复杂的条件,可能需要使用更复杂的技术,如“隧道技术”。
SHA-1的弱点主要源于:
- 其消息扩展过程的线性性,使得输入差异的传播可以被精确跟踪和控制。
- 非线性函数的某些输入/输出差异对出现的概率较高,可被利用。
第三部分:SHA-1碰撞攻击的实际技术演进
SHA-1碰撞攻击的研究经历了多年的发展:
-
早期分析(2005年之前):研究者发现了SHA-0和SHA-1的弱点,但需要大量计算(> 2⁶⁹)。
-
王小云等人的突破(2005年):中国密码学家王小云团队提出了理论上的碰撞攻击,将复杂度降至约2⁶⁹,但仍在计算上不可行。
-
SHAttered攻击(2017年):由Google和CWI研究所的团队(Marc Stevens等)首次公开实现了SHA-1的实际碰撞。他们利用了一种改进的差分路径和高效的消息修改技术,核心步骤是:
a. 选择前缀攻击:与早期固定前缀攻击不同,这种攻击允许攻击者为两个碰撞文件选择任意的、不同的前缀。这意味着攻击者可以在两个看似完全不同的文件(如PDF、程序)中制造相同的SHA-1哈希值。
b. 构建复杂的差分路径:他们设计了一个跨越80轮、包含大量条件的差分路径。这个路径从消息扩展就开始控制差异的传播。
c. GPU加速与计算优化:
- 攻击将寻找碰撞的过程转化为一个“可满足性问题”(SAT)。
- 通过利用GPU的并行计算能力,将计算量降低到实际可行的水平(约2⁶³.1次哈希计算,相当于1100万GPU小时,在2017年实际花费约10万美元的云算力)。
- 使用了“非线性局部冲突”技术,在路径中间故意引入局部冲突,然后将其化解,从而简化后续条件。
d. 产生实际碰撞文件:他们最终生成了两个内容不同但SHA-1值完全相同的PDF文件。这是通过精心构造PDF文件格式,将碰撞数据隐藏在“注释”或“图片数据”等可忽略区域实现的。
第四部分:SHA-1碰撞实例的深入分析
我们以著名的“SHAttered”实例(两个不同的PDF文件,相同的SHA-1值)为例,具体分析其碰撞是如何构造的。这里不列出具体的比特序列,而是解释其构造逻辑:
-
文件结构设计:
- 文件A和文件B都包含一个正常的PDF头部和可显示的内容(如图像、文字)。
- 在文件末尾,附加了两个精心构造的“碰撞块”(每个块512位,即64字节)。这两个碰撞块是不同的,但各自与前面的文件内容结合后,产生了相同的哈希值。
-
碰撞块的构造过程:
a. 起始状态:攻击者计算文件公共前缀(相同的PDF内容)的SHA-1中间状态。这个状态作为“链接变量”(Chaining Variable)成为后续碰撞计算的起点。b. 注入差异:在第一个碰撞块中,攻击者引入一个特定的比特差异模式∆。这个∆是经过精心选择的,使得它经过SHA-1的80轮处理后,在输出端(即第一个碰撞块处理完时的哈希状态)产生另一个我们希望看到的差异模式∆'。
c. 纠正差异:第二个碰撞块被设计用来“纠正”从第一个块传递下来的差异∆'。即,第二个碰撞块本身也包含一个差异,但该差异经过SHA-1处理后,恰好抵消了∆'的影响,使得最终处理完两个碰撞块后的哈希状态完全一致。
-
技术核心:整个攻击的成败关键在于:
- 第一个碰撞块的差异∆在经过SHA-1压缩后,必须产生一个特定的∆'。∆'必须满足“可纠正”的条件,即存在另一个消息块(第二个碰撞块),其差异能够精确抵消∆'。
- 这需要满足数百个中间条件(比特约束)。攻击者通过“消息修改”来满足早期条件,并通过大量搜索(利用GPU并行)来满足后期复杂条件。
-
实际影响:
- 这两个PDF文件在常规PDF阅读器中显示为不同的内容(例如,一份是普通文档,另一份可能包含恶意内容或不同条款)。
- 但它们的SHA-1校验和完全一样。如果一个系统(如版本控制系统Git早期版本、某些备份软件)依赖SHA-1来唯一标识文件,它就无法区分这两个文件,可能导致安全漏洞。
总结与启示
SHA-1碰撞攻击的成功标志着该算法在密码学意义上被实际攻破。其核心教训是:
-
差分分析的威力:通过精心构造输入差异,并利用哈希函数组件的数学特性(线性消息扩展、非线性函数的差分特性),可以将指数级的碰撞搜索转化为可控的约束求解问题。
-
计算能力的进步:随着GPU和定制硬件的发展,原本理论上的攻击可以变得实际可行。
-
迁移到更安全算法:由于SHA-1的碰撞攻击已变得实际可行,所有安全应用都应迁移到更安全的哈希算法,如SHA-256、SHA-3等。
SHA-1的案例完美展示了密码算法的生命周期:从被设计、广泛应用,到理论分析发现弱点,再到实际攻击实现,最终被淘汰。它强调了密码学中“纵深防御”和“及时升级”的重要性。