SHA-256 哈希算法的轮函数中的 Σ0 和 Σ1 函数详解
1. 题目描述
SHA-256 算法是一种广泛使用的密码学哈希函数,它将任意长度的输入消息压缩为固定长度(256位)的输出。其核心是“压缩函数”,而压缩函数的核心又是“轮函数”。轮函数在 64 轮运算中,不断更新 8 个工作寄存器(a, b, c, d, e, f, g, h)的状态。在每轮计算中,会用到两个特殊的函数:Σ0(读作“Sigma 0”)和 Σ1(读作“Sigma 1”)。本题要求深入剖析 SHA-256 轮函数中 Σ0 和 Σ1 函数的作用、定义、计算过程以及它们在算法安全设计中的目的。
2. 背景与预备知识
- 哈希函数:一种单向密码学函数,将任意长度的数据映射为固定长度的“摘要”。
- SHA-256 流程概览:
- 消息填充:将输入消息填充至长度为 512 位的整数倍。
- 消息分块:将填充后的消息分割成多个 512 位的块。
- 迭代压缩:对每个 512 位的消息块,执行一次“压缩函数”。压缩函数接收两个输入:当前块的 512 位数据,以及上一个压缩函数的 256 位输出(称为“链接变量”或“中间哈希值”,初始值为一组预定义的常量)。其输出是新的 256 位链接变量,用于处理下一个块。
- 最终输出:处理完所有消息块后,最终的链接变量即为最终的哈希值。
- SHA-256 压缩函数:其核心是将 512 位的消息块扩展为 64 个 32 位的字(W₀ 到 W₆₃),并初始化 8 个 32 位工作寄存器 (a, b, c, d, e, f, g, h) 为当前的链接变量。然后,它会进行 64 轮运算,每轮使用一个字 Wₜ 和一个轮常数 Kₜ 来更新这 8 个寄存器。
- 寄存器更新规则:SHA-256 轮函数的更新公式如下(这是理解 Σ0 和 Σ1 的关键上下文):
T1 = h + Σ1(e) + Ch(e, f, g) + K_t + W_t
T2 = Σ0(a) + Maj(a, b, c)
h = g
g = f
f = e
e = d + T1
d = c
c = b
b = a
a = T1 + T2
其中Ch是“选择”函数,Maj是“多数”函数,K_t是轮常数,W_t是消息调度字。
3. Σ0 和 Σ1 函数的定义与计算步骤
Σ0 和 Σ1 是作用于单个 32 位字(寄存器值)上的线性函数。它们的计算基于循环右移(Right Rotate, 记作 ROTR)操作。
- 循环右移 (ROTR):给定一个 32 位字 X,
ROTR^n(X)表示将 X 向右循环移位 n 位。例如,对于 8 位字0b10010110,ROTR^3的结果是0b11010010。
Σ0 函数 (作用于寄存器 a)
- 定义:
Σ0(x) = ROTR^2(x) ⊕ ROTR^13(x) ⊕ ROTR^22(x) - 计算步骤:
- 对输入值
a进行循环右移 2 位,得到值 A。 - 对输入值
a进行循环右移 13 位,得到值 B。 - 对输入值
a进行循环右移 22 位,得到值 C。 - 将 A, B, C 这三个 32 位中间结果进行按位异或 (XOR) 运算。
- 异或的结果就是
Σ0(a)的输出。
- 对输入值
Σ1 函数 (作用于寄存器 e)
- 定义:
Σ1(x) = ROTR^6(x) ⊕ ROTR^11(x) ⊕ ROTR^25(x) - 计算步骤:
- 对输入值
e进行循环右移 6 位,得到值 D。 - 对输入值
e进行循环右移 11 位,得到值 E。 - 对输入值
e进行循环右移 25 位,得到值 F。 - 将 D, E, F 这三个 32 位中间结果进行按位异或 (XOR) 运算。
- 异或的结果就是
Σ1(e)的输出。
- 对输入值
示例(简化 4 位字):
假设当前轮函数输入 a = 0b1011 (4 位简化)。
计算 Σ0(a)(使用定义,但位宽仅为示例):
ROTR^2(a) = 0b1110
ROTR^13(a) 在 4 位系统无意义,但逻辑等同于右移,此处仅为说明步骤顺序。
实际 SHA-256 中操作的是 32 位字。
4. Σ0 和 Σ1 在轮函数中的作用
回顾寄存器更新规则:
-
T1 = h + Σ1(e) + Ch(e, f, g) + K_t + W_t -
T2 = Σ0(a) + Maj(a, b, c) -
Σ1(e) 的作用:
- 它是计算
T1的五个组成部分之一。T1主要用于更新寄存器e(e = d + T1)。 Σ1(e)从当前寄存器e的比特中,通过循环移位和异或,扩散和混淆了e的比特信息,并将这个结果注入到T1中。这为e的更新提供了非线性(通过Ch函数)和线性扩散(通过Σ1自身)的混合输入。它确保了e的新值不仅依赖于外部输入(W_t, K_t)和相邻寄存器的值(h, d),还强烈依赖于e自身历史的、经过复杂变换的版本。这增加了比特之间的依赖关系,使得反向计算或寻找碰撞变得困难。
- 它是计算
-
Σ0(a) 的作用:
- 它是计算
T2的两个组成部分之一。T2和T1相加得到新的寄存器a的值(a = T1 + T2)。 Σ0(a)从当前寄存器a的比特中,通过循环移位和异或,扩散和混淆了a的比特信息,并将这个结果注入到T2中。T2的另一部分是Maj(a, b, c),它混合了a, b, c三个寄存器。因此,新的a的值,由来自e, f, g, h, d路径的T1和来自a, b, c路径的T2共同决定。Σ0(a)确保了“a路径”上的信息是经过充分混淆的,而不是简单地传递。这是 SHA-256 设计中“雪崩效应”的关键环节——改变输入的一位,会导致输出的每一位都有约 50% 的概率发生变化。
- 它是计算
5. 设计目标与安全性分析
Σ0 和 Σ1 的设计并非随意,而是精心选择的,旨在满足以下几个密码学目标:
- 比特扩散 (Bit Diffusion):循环右移操作(如 2, 13, 22, 6, 11, 25)能将单个输入位的影响扩散到输出的多个位置。异或操作进一步混合了这些被移位的位。这确保了输入位(寄存器
a或e的位)的微小变化,能快速传播到 Σ 函数的整个 32 位输出中。 - 非线性/伪随机性 (Non-linearity / Pseudorandomness):虽然 Σ0 和 Σ1 本身是线性操作(因为循环移位和异或都是线性的),但它们的输出是输入位的复杂线性组合。当这个输出与轮函数中其他高度非线性的部分(如
Ch,Maj函数)以及模加法结合时,整体的轮函数表现出极强的非线性和伪随机性,使得从输出推断输入或寻找数学结构上的弱点变得极其困难。 - 打破对称性 (Breaking Symmetry):Σ0 和 Σ1 使用的位移常数((2,13,22) 和 (6,11,25))是经过仔细挑选的。它们与轮函数中其他位移常数(例如在消息调度中使用的 σ0 和 σ1 函数)一起,旨在打破算法中可能出现的任何形式的对称性或周期性,从而抵抗密码分析攻击,如固定点攻击、差分攻击和线性攻击。
- 高效计算 (Efficient Computation):在硬件和软件实现中,循环移位和异或都是非常快速、成本低廉的操作。这使得 SHA-256 在提供强大安全性的同时,也能保持很高的运算效率。
总结:
SHA-256 轮函数中的 Σ0 和 Σ1 函数,本质上是基于循环右移和异或的线性扩散函数。它们分别作用于关键的中间状态寄存器 a 和 e 上,将单个寄存器的比特信息复杂地扩散到 32 位的输出中。它们的主要角色是将寄存器当前状态的高度混淆版本,分别注入到更新路径 T2 和 T1 中,从而与其他非线性组件(Ch, Maj)和外部输入(W_t, K_t)紧密结合,共同确保了 SHA-256 压缩函数每一轮都产生强烈的雪崩效应和非线性,是构成其抗碰撞性和前像抵抗能力的关键基础构件之一。