BLAKE2哈希算法的压缩函数设计
字数 2975 2025-12-17 02:48:46

BLAKE2哈希算法的压缩函数设计

好的,我们先看题目描述。BLAKE2 是一种广泛使用的、速度很快的密码学哈希函数,它是 SHA-3 竞赛入围算法 BLAKE 的改进版。BLAKE2 家族包含 BLAKE2b(输出 512 位,适用于 64 位平台)和 BLAKE2s(输出 256 位,适用于 32 位平台)。它的核心创新和性能优势很大程度上来源于其压缩函数的设计,该函数结合了 HAIFA 迭代结构和一个类 ChaCha 的核心排列。

下面,我将循序渐进地讲解 BLAKE2 压缩函数的设计细节。


第一步:理解压缩函数在整个哈希过程中的位置

  1. 回顾哈希函数一般结构:像 SHA-256 一样,大多数哈希函数采用 Merkle-Damgård 迭代结构或其变体。BLAKE2 采用的是 HAIFA 迭代结构,它是对 Merkle-Damgård 的加强,引入了额外的输入(如消息位长度、盐值等)来抵抗一些特定攻击。
  2. 压缩函数的作用:无论采用何种迭代结构,其“发动机”都是一个压缩函数。它的任务是:接收一个固定大小的 内部状态(或叫链接变量) 和一个 消息分组,进行一轮复杂的混合运算,输出一个新的、与输入大小相同的内部状态。
  3. BLAKE2 的输入输出:对于 BLAKE2b,压缩函数 F 定义为:
    F(h, m, t, f)h'
    • h:输入的状态向量,8个 64 位字(总共 512 位)。
    • m:输入的消息块,16个 64 位字(总共 1024 位)。
    • t:一个 2 字的计数器,表示当前已处理的消息字节总数。这是 HAIFA 结构的关键,增加了位置敏感性。
    • f:一个标志字,如果这是最后一个消息块,则置为一个特定值(类似 MD/SHA 系列的填充指示位)。

第二步:压缩函数的初始化——构建初始向量 V

压缩函数的第一步不是直接操作输入的状态 h,而是先构建一个更大的 16 字(对于 BLAKE2b 是 16×64 位)的工作向量 V

  1. V 的低 8 个字(V[0..7]):直接复制自输入状态 h[0..7]。这部分代表了哈希计算的“当前进度”。
  2. V 的第 8 到 15 个字(V[8..15]):这是 BLAKE2 设计的一个巧妙之处,它直接植入了算法的一些常量、计数器 t 和标志 f,将它们与核心运算深度绑定,而不是简单地预处理或后处理。
    • V[8..11]:设置为四个初始化常量 IV[0..3]。这些常量与 SHA-512 的初值类似,由圆周率 π 的小数部分平方根生成,确保“无后门”。
    • V[12..13]:设置为计数器 t 的两个字。t[0] 是低位,t[1] 是高位。这使得压缩函数处理每个消息块的上下文都不同(因为 t 在增长),极大地增强了算法的安全性。
    • V[14..15]:设置为标志 f 的两个字。对于中间块,f = 0;对于最后一个块,f = (0xFFFFFFFFFFFFFFFF)(全1)。这使得压缩函数能明确感知到这是不是最后一个块。

通过这种方式,消息、计数器、标志和初始常量在运算的一开始就与当前状态 h 并置在同一个向量 V 中。


第三步:核心运算——类 ChaCha 的 G 函数轮运算

这是 BLAKE2 压缩函数的核心和性能关键。它大量借鉴了流密码 ChaCha 的设计思想,使用一系列简单、高效的 ARX(加法、循环移位、异或)操作。

  1. G 函数:这是最小的混合单元。一次 G 函数调用会混合 V 中的 4 个字,并用到消息 m 中的 2 个字。对于 BLAKE2b,G 函数操作 64 位字,定义如下:

    # 伪代码表示
    def G(v, a, b, c, d, x, y):
        v[a] = (v[a] + v[b] + x) & 0xFFFFFFFFFFFFFFFF  # 加法,模 2^64
        v[d] = rotate_right(v[d] ^ v[a], 32)           # 异或和循环右移(对BLAKE2b是32位)
        v[c] = (v[c] + v[d]) & 0xFFFFFFFFFFFFFFFF
        v[b] = rotate_right(v[b] ^ v[c], 24)           # 循环右移24位
        v[a] = (v[a] + v[b] + y) & 0xFFFFFFFFFFFFFFFF
        v[d] = rotate_right(v[d] ^ v[a], 16)           # 循环右移16位
        v[c] = (v[c] + v[d]) & 0xFFFFFFFFFFFFFFFF
        v[b] = rotate_right(v[b] ^ v[c], 63)           # 循环右移63位(这个63很重要,是BLAKE的特色)
    

    注意:

    • a, b, c, d 是指向 V 向量中 4 个特定位置的索引。
    • x, y 是来自当前消息块 m 的两个字。这确保了消息数据被直接、高强度地混入状态中。
    • 运算包括模加、异或和循环移位。循环移位的位数(32, 24, 16, 63)是经过精心挑选的,以最大化扩散速度和实现非线性。
  2. 一轮(Round)运算:一轮运算由 8 次 G 函数调用组成,覆盖 V 向量的所有 16 个字,并消耗消息块 m 的全部 16 个字(每个字被使用一次)。一轮中 G 函数的调用顺序(即 a, b, c, d 的索引选择)也经过特别设计,通常称为“排列”或“调度”。

    • 对于 BLAKE2b,典型的排列(列步和行步)确保状态矩阵的每一列每一对角线上相邻的四个字都能被一个 G 函数充分混合。
  3. 总轮数:为了平衡安全与效率,BLAKE2 压缩函数执行 12 轮(BLAKE2b)或 10 轮(BLAKE2s)。这比其前身 BLAKE 的轮数(14/16轮)要少,但分析表明这已足够安全,并且带来了显著的性能提升。


第四步:压缩函数的最终输出

在执行完所有轮次后,16 字的工作向量 V 已经完成了与消息、计数器、标志的充分混合。现在需要从这个混合结果中,提取出新的 8 字内部状态 h'

  1. 提取新状态
    • 新的状态 h' 的前 8 个字(h'[0..7])通过一个简单的运算得到:
      h'[i] = h[i] XOR V[i] XOR V[i+8],其中 i 从 0 到 7。
  2. 为什么这样设计?
    • V[i] 是初始状态 h[i] 与常量/计数器/标志经过多轮混合后的结果。
    • V[i+8] 是那些常量/计数器/标志自身与状态混合后的结果。
    • 异或(XOR) 操作确保了这是一个可逆的、无进位溢出的组合。它结合了旧状态和本轮运算的全部成果。
    • 这种“旧状态 XOR 新向量”的构造模式,在密码学上被称为 Davies-Meyer 结构,是构建抗碰撞哈希函数的常用且被证明安全的方法。

总结与特性

让我们梳理一下 BLAKE2 压缩函数设计的精妙之处:

  1. HAIFA 结构集成:通过将计数器 t 和标志 f 直接输入到工作向量 V 中,使其参与每一轮的运算,天然支持了 HAIFA 结构,增强了抵抗长度扩展攻击和某些多碰撞攻击的能力。
  2. ARX 设计哲学:基于加、循环移位、异或的 G 函数在现代 CPU(尤其是 64 位和 SIMD 指令集)上运行效率极高,这是 BLAKE2 速度领先的关键。
  3. 宽管道(Wide Pipe):内部工作状态 V(1024位)是最终输出/输入状态 h(512位)的两倍宽。这提供了强大的内部安全性余量。
  4. 深度消息注入:消息的每一个字,在每一轮中都被精确地使用一次,确保了消息比特的快速扩散。
  5. 精心挑选的常数:初始化常量、循环移位数、G 函数的调度顺序都经过密码学分析,旨在打破对称性、防止固定点、实现最优扩散。

因此,BLAKE2 压缩函数是一个将安全性证明(基于 HAIFA、Davies-Meyer 结构)、高性能实现(ARX 操作)和简洁优雅设计完美结合的典范。它在许多性能测试中超越 SHA-256 和 SHA-3,被广泛应用于文件校验、密码存储、区块链(如 Arweave)和许多需要高速哈希的场景中。

BLAKE2哈希算法的压缩函数设计 好的,我们先看题目描述。BLAKE2 是一种广泛使用的、速度很快的密码学哈希函数,它是 SHA-3 竞赛入围算法 BLAKE 的改进版。BLAKE2 家族包含 BLAKE2b(输出 512 位,适用于 64 位平台)和 BLAKE2s(输出 256 位,适用于 32 位平台)。它的核心创新和性能优势很大程度上来源于其 压缩函数 的设计,该函数结合了 HAIFA 迭代结构和一个类 ChaCha 的核心排列。 下面,我将循序渐进地讲解 BLAKE2 压缩函数的设计细节。 第一步:理解压缩函数在整个哈希过程中的位置 回顾哈希函数一般结构 :像 SHA-256 一样,大多数哈希函数采用 Merkle-Damgård 迭代结构或其变体。BLAKE2 采用的是 HAIFA 迭代结构 ,它是对 Merkle-Damgård 的加强,引入了额外的输入(如消息位长度、盐值等)来抵抗一些特定攻击。 压缩函数的作用 :无论采用何种迭代结构,其“发动机”都是一个压缩函数。它的任务是:接收一个固定大小的 内部状态(或叫链接变量) 和一个 消息分组 ,进行一轮复杂的混合运算,输出一个新的、与输入大小相同的内部状态。 BLAKE2 的输入输出 :对于 BLAKE2b,压缩函数 F 定义为: F(h, m, t, f) → h' h :输入的状态向量,8个 64 位字(总共 512 位)。 m :输入的消息块,16个 64 位字(总共 1024 位)。 t :一个 2 字的计数器,表示当前已处理的 消息字节总数 。这是 HAIFA 结构的关键,增加了位置敏感性。 f :一个标志字,如果这是最后一个消息块,则置为一个特定值(类似 MD/SHA 系列的填充指示位)。 第二步:压缩函数的初始化——构建初始向量 V 压缩函数的第一步不是直接操作输入的状态 h ,而是先构建一个更大的 16 字(对于 BLAKE2b 是 16×64 位)的工作向量 V 。 V 的低 8 个字(V[ 0..7]) :直接复制自输入状态 h[0..7] 。这部分代表了哈希计算的“当前进度”。 V 的第 8 到 15 个字(V[ 8..15]) :这是 BLAKE2 设计的一个 巧妙之处 ,它直接植入了算法的一些常量、计数器 t 和标志 f ,将它们与核心运算 深度绑定 ,而不是简单地预处理或后处理。 V[8..11] :设置为四个 初始化常量 IV[0..3] 。这些常量与 SHA-512 的初值类似,由圆周率 π 的小数部分平方根生成,确保“无后门”。 V[12..13] :设置为计数器 t 的两个字。 t[0] 是低位, t[1] 是高位。这使得压缩函数处理 每个消息块的上下文都不同 (因为 t 在增长),极大地增强了算法的安全性。 V[14..15] :设置为标志 f 的两个字。对于中间块, f = 0 ;对于最后一个块, f = (0xFFFFFFFFFFFFFFFF) (全1)。这使得压缩函数能明确感知到这是不是最后一个块。 通过这种方式,消息、计数器、标志和初始常量在运算的一开始就与当前状态 h 并置 在同一个向量 V 中。 第三步:核心运算——类 ChaCha 的 G 函数轮运算 这是 BLAKE2 压缩函数的核心和性能关键。它大量借鉴了流密码 ChaCha 的设计思想,使用一系列简单、高效的 ARX(加法、循环移位、异或)操作。 G 函数 :这是最小的混合单元。一次 G 函数调用会混合 V 中的 4 个字,并用到消息 m 中的 2 个字。对于 BLAKE2b, G 函数操作 64 位字,定义如下: 注意: a, b, c, d 是指向 V 向量中 4 个特定位置的索引。 x, y 是来自当前消息块 m 的两个字。这确保了消息数据被直接、高强度地混入状态中。 运算包括模加、异或和循环移位。循环移位的位数(32, 24, 16, 63)是经过精心挑选的,以最大化扩散速度和实现非线性。 一轮(Round)运算 :一轮运算由 8 次 G 函数调用组成,覆盖 V 向量的所有 16 个字,并消耗消息块 m 的全部 16 个字(每个字被使用一次)。一轮中 G 函数的调用顺序(即 a, b, c, d 的索引选择)也经过特别设计,通常称为“排列”或“调度”。 对于 BLAKE2b,典型的排列(列步和行步)确保状态矩阵的 每一列 和 每一对角线上相邻的四个字 都能被一个 G 函数充分混合。 总轮数 :为了平衡安全与效率,BLAKE2 压缩函数 执行 12 轮 (BLAKE2b)或 10 轮(BLAKE2s)。这比其前身 BLAKE 的轮数(14/16轮)要少,但分析表明这已足够安全,并且带来了显著的性能提升。 第四步:压缩函数的最终输出 在执行完所有轮次后,16 字的工作向量 V 已经完成了与消息、计数器、标志的充分混合。现在需要从这个混合结果中,提取出新的 8 字内部状态 h' 。 提取新状态 : 新的状态 h' 的前 8 个字( h'[0..7] )通过一个简单的运算得到: h'[i] = h[i] XOR V[i] XOR V[i+8] ,其中 i 从 0 到 7。 为什么这样设计? V[i] 是初始状态 h[i] 与常量/计数器/标志经过多轮混合后的结果。 V[i+8] 是那些常量/计数器/标志自身与状态混合后的结果。 异或(XOR) 操作确保了这是一个可逆的、无进位溢出的组合。它结合了旧状态和本轮运算的全部成果。 这种“旧状态 XOR 新向量”的构造模式,在密码学上被称为 Davies-Meyer 结构 ,是构建抗碰撞哈希函数的常用且被证明安全的方法。 总结与特性 让我们梳理一下 BLAKE2 压缩函数设计的精妙之处: HAIFA 结构集成 :通过将计数器 t 和标志 f 直接输入到工作向量 V 中,使其参与每一轮的运算,天然支持了 HAIFA 结构,增强了抵抗长度扩展攻击和某些多碰撞攻击的能力。 ARX 设计哲学 :基于加、循环移位、异或的 G 函数在现代 CPU(尤其是 64 位和 SIMD 指令集)上运行效率极高,这是 BLAKE2 速度领先的关键。 宽管道(Wide Pipe) :内部工作状态 V (1024位)是最终输出/输入状态 h (512位)的两倍宽。这提供了强大的内部安全性余量。 深度消息注入 :消息的每一个字,在每一轮中都被精确地使用一次,确保了消息比特的快速扩散。 精心挑选的常数 :初始化常量、循环移位数、 G 函数的调度顺序都经过密码学分析,旨在打破对称性、防止固定点、实现最优扩散。 因此,BLAKE2 压缩函数是一个将安全性证明(基于 HAIFA、Davies-Meyer 结构)、高性能实现(ARX 操作)和简洁优雅设计完美结合的典范。它在许多性能测试中超越 SHA-256 和 SHA-3,被广泛应用于文件校验、密码存储、区块链(如 Arweave)和许多需要高速哈希的场景中。