SM4分组密码算法的密钥扩展算法中常数FK与CK的详细作用与设计依据
字数 2961 2025-12-09 13:52:36

SM4分组密码算法的密钥扩展算法中常数FK与CK的详细作用与设计依据

我们先来回顾一下SM4算法的基本框架,它是一个分组长度为128比特、密钥长度为128比特的分对称密码算法,采用32轮非线性迭代结构。在每一轮迭代中,都需要使用一个32比特的轮密钥。密钥扩展算法的任务,就是从那个128比特的用户密钥,生成这32个轮密钥。这个过程依赖于两组非常重要的常数:系统参数FK和固定参数CK。今天我们就深入剖析这两组常数的具体数值、在算法中扮演的角色,以及它们如此设计的背后考量。

第一步:明确密钥扩展算法的整体流程

我们先不深入FK和CK,而是俯瞰整个密钥扩展过程,了解FK和CK出现在哪里。这有助于理解它们的功能定位。

给定一个128比特的加密密钥 \(MK = (MK_0, MK_4, MK_1, MK_2, MK_3)\),其中每个\(MK_i\)是32比特。密钥扩展算法步骤如下:

  1. 中间密钥(\(K_i\))初始化:首先,将用户密钥的四个部分与四个系统参数FK进行异或,得到四个初始的中间密钥。

\[ (K_0, K_1, K_2, K_3) = (MK_0 \oplus FK_0, MK_1 \oplus FK_1, MK_2 \oplus FK_2, MK_3 \oplus FK_3) \]

**这里,FK第一次出现。**
  1. 轮密钥(\(rk_i\))迭代生成:对于 \(i = 0, 1, ..., 31\)(生成第i轮的轮密钥 \(rk_i\)),执行以下计算:

\[ rk_i = K_{i+4} = K_i \oplus T'(K_{i+1} \oplus K_{i+2} \oplus K_{i+3} \oplus CK_i) \]

其中,$ T' $ 是一个可逆变换,其结构与加密轮函数中的 $ T $ 变换类似,但线性变换 $ L' $ 与加密中的 $ L $ 不同。$ CK_i $ 是一个32比特的固定参数。
**这里,CK在每一轮迭代中都会使用,每个 $ i $ 对应一个不同的 $ CK_i $。**

第二步:深入剖析系统参数FK的作用与设计

  1. FK的数值:FK由4个32比特常数构成:

\[ FK_0 = A3B1BAC6, \quad FK_1 = 56AA3350, \quad FK_2 = 677D9197, \quad FK_3 = B27022DC \]

这些数值是固定的,在标准中预先定义。
  1. FK的核心作用

    • 消除弱密钥:这是FK最主要的作用。在某些分组密码中,特定的密钥(称为弱密钥)会导致加密强度显著下降。SM4在密钥扩展的第一步就将用户密钥与FK进行异或,相当于对原始密钥进行了一个“预处理”或“漂白”。这个操作打破了用户密钥可能具有的某种数学结构(例如全0、全1,或某些对称模式),确保即使输入的是一个“弱”的用户密钥,经过与FK异或后得到的中间密钥 \((K_0, K_1, K_2, K_3)\) 也具有良好的随机性,从而在后续迭代中生成的所有轮密钥都不会呈现出规律性,有效防范了基于弱密钥的攻击。
    • 增加算法标识:FK的取值并非来自数学常数,而是人为选择的固定值。这为SM4算法打上了一个独特的“印记”,使其与采用类似结构的其他密码算法区分开来,从某种意义上也增加了算法的专有特性。
  2. FK的设计依据:FK的取值看似随机,但选择时也考虑了一些因素。它们通常是“不规则的”十六进制数,没有明显的数学模式(如递增序列、循环移位等),这有助于最大化其“破坏”用户密钥原有结构的能力。其具体数值是通过在有限域上计算特定函数或精心挑选得到的,以确保良好的统计特性。

第三步:深入剖析固定参数CK的作用与设计

  1. CK的生成:CK不是一个单一常数,而是一个包含32个32比特常数 \(CK_0, CK_1, ..., CK_{31}\) 的数组。每个 \(CK_i\) 通过一个确定的公式生成,确保了可复现性和标准统一性。
    具体生成方法为:设 \(ck_{i,j}\)\(CK_i\) 的第 \(j\) 个字节(\(j=0,1,2,3\)),则:

\[ ck_{i,j} = (4i + j) \times 7 \pmod{256} \]

然后,$ CK_i = (ck_{i,0}, ck_{i,1}, ck_{i,2}, ck_{i,3}) $,即四个字节拼接成一个32比特字。例如,$ CK_0 = (0,1,2,3) $ 对应 `0x00010203`。
  1. CK的核心作用

    • 打破对称性,确保轮密钥差异:密钥扩展的迭代公式 \(K_{i+4} = K_i \oplus T'(K_{i+1} \oplus K_{i+2} \oplus K_{i+3} \oplus CK_i)\) 本质上是基于前面四个 \(K\) 值生成下一个。如果没有 \(CK_i\),这个生成过程将完全由之前的 \(K\) 值确定,具有高度的“内部对称性”。攻击者可能利用这种对称性推导出密钥之间的关系。引入与轮数 \(i\) 相关的 \(CK_i\),相当于在每一轮迭代中加入了一个独特的“扰动”或“轮常量”。这使得每一轮生成的轮密钥 \(rk_i\) 都不同,并且轮密钥之间不存在简单的线性或差分关系,极大地增强了密钥扩展算法的非线性复杂性,是抵抗相关密钥攻击和滑动攻击的关键设计。
  2. CK的设计依据

    • 简单、高效、无歧义:其生成规则 \((4i+j)*7 \mod 256\) 非常简单,计算速度快,无需在算法实现中存储一个大的常量表,可以即时计算,节省存储空间。
    • 伪随机性:乘法因子7和模256运算,确保了生成的字节序列在统计上看起来是随机的,没有明显的规律。虽然简单,但已足够为每一轮提供一个独特的、不可预测的输入。
    • 可证明性:这种确定性的、简单的生成方式,便于在算法安全性证明中进行形式化分析。

第四步:总结与关联

现在,让我们将FK和CK的作用串联起来,看它们如何协同工作:

  1. 初始化阶段(FK负责):用户密钥 \(MK\) 进入后,首先用 FK 进行“预处理”,目的是消除输入密钥的固有弱点,为密钥扩展提供一个良好的、无结构性弱点的起始状态 \((K_0, K_1, K_2, K_3)\)
  2. 扩展阶段(CK负责):在从起始状态迭代生成32个轮密钥的过程中,每一轮都引入一个不同的 CK_i 作为“轮常量”,目的是打破迭代过程的内部对称性和线性,确保生成的轮密钥之间相互独立、不具相关性,从而抵抗针对密钥扩展算法的各类分析攻击。

简单来说,FK负责“净化”输入的原料(密钥),CK负责“调味”每一步加工过程(迭代),两者共同确保了SM4算法最终使用的“调料”(轮密钥)既安全又独特。这种“初始异或常量+轮常量”的设计模式,是许多现代分组密码(如AES)密钥扩展中的常见且有效的安全措施。

SM4分组密码算法的密钥扩展算法中常数FK与CK的详细作用与设计依据 我们先来回顾一下SM4算法的基本框架,它是一个分组长度为128比特、密钥长度为128比特的分对称密码算法,采用32轮非线性迭代结构。在每一轮迭代中,都需要使用一个32比特的轮密钥。密钥扩展算法的任务,就是从那个128比特的用户密钥,生成这32个轮密钥。这个过程依赖于两组非常重要的常数:系统参数FK和固定参数CK。今天我们就深入剖析这两组常数的具体数值、在算法中扮演的角色,以及它们如此设计的背后考量。 第一步:明确密钥扩展算法的整体流程 我们先不深入FK和CK,而是俯瞰整个密钥扩展过程,了解FK和CK出现在哪里。这有助于理解它们的功能定位。 给定一个128比特的加密密钥 \( MK = (MK_ 0, MK_ 4, MK_ 1, MK_ 2, MK_ 3) \),其中每个\( MK_ i \)是32比特。密钥扩展算法步骤如下: 中间密钥(\( K_ i \))初始化 :首先,将用户密钥的四个部分与四个系统参数FK进行异或,得到四个初始的中间密钥。 \[ (K_ 0, K_ 1, K_ 2, K_ 3) = (MK_ 0 \oplus FK_ 0, MK_ 1 \oplus FK_ 1, MK_ 2 \oplus FK_ 2, MK_ 3 \oplus FK_ 3) \] 这里,FK第一次出现。 轮密钥(\( rk_ i \))迭代生成 :对于 \( i = 0, 1, ..., 31 \)(生成第i轮的轮密钥 \( rk_ i \)),执行以下计算: \[ rk_ i = K_ {i+4} = K_ i \oplus T'(K_ {i+1} \oplus K_ {i+2} \oplus K_ {i+3} \oplus CK_ i) \] 其中,\( T' \) 是一个可逆变换,其结构与加密轮函数中的 \( T \) 变换类似,但线性变换 \( L' \) 与加密中的 \( L \) 不同。\( CK_ i \) 是一个32比特的固定参数。 这里,CK在每一轮迭代中都会使用,每个 \( i \) 对应一个不同的 \( CK_ i \)。 第二步:深入剖析系统参数FK的作用与设计 FK的数值 :FK由4个32比特常数构成: \[ FK_ 0 = A3B1BAC6, \quad FK_ 1 = 56AA3350, \quad FK_ 2 = 677D9197, \quad FK_ 3 = B27022DC \] 这些数值是固定的,在标准中预先定义。 FK的核心作用 : 消除弱密钥 :这是FK最主要的作用。在某些分组密码中,特定的密钥(称为弱密钥)会导致加密强度显著下降。SM4在密钥扩展的第一步就将用户密钥与FK进行异或,相当于对原始密钥进行了一个“预处理”或“漂白”。这个操作打破了用户密钥可能具有的某种数学结构(例如全0、全1,或某些对称模式),确保即使输入的是一个“弱”的用户密钥,经过与FK异或后得到的中间密钥 \( (K_ 0, K_ 1, K_ 2, K_ 3) \) 也具有良好的随机性,从而在后续迭代中生成的所有轮密钥都不会呈现出规律性,有效防范了基于弱密钥的攻击。 增加算法标识 :FK的取值并非来自数学常数,而是人为选择的固定值。这为SM4算法打上了一个独特的“印记”,使其与采用类似结构的其他密码算法区分开来,从某种意义上也增加了算法的专有特性。 FK的设计依据 :FK的取值看似随机,但选择时也考虑了一些因素。它们通常是“不规则的”十六进制数,没有明显的数学模式(如递增序列、循环移位等),这有助于最大化其“破坏”用户密钥原有结构的能力。其具体数值是通过在有限域上计算特定函数或精心挑选得到的,以确保良好的统计特性。 第三步:深入剖析固定参数CK的作用与设计 CK的生成 :CK不是一个单一常数,而是一个包含32个32比特常数 \( CK_ 0, CK_ 1, ..., CK_ {31} \) 的数组。每个 \( CK_ i \) 通过一个确定的公式生成,确保了可复现性和标准统一性。 具体生成方法为:设 \( ck_ {i,j} \) 为 \( CK_ i \) 的第 \( j \) 个字节(\( j=0,1,2,3 \)),则: \[ ck_ {i,j} = (4i + j) \times 7 \pmod{256} \] 然后,\( CK_ i = (ck_ {i,0}, ck_ {i,1}, ck_ {i,2}, ck_ {i,3}) \),即四个字节拼接成一个32比特字。例如,\( CK_ 0 = (0,1,2,3) \) 对应 0x00010203 。 CK的核心作用 : 打破对称性,确保轮密钥差异 :密钥扩展的迭代公式 \( K_ {i+4} = K_ i \oplus T'(K_ {i+1} \oplus K_ {i+2} \oplus K_ {i+3} \oplus CK_ i) \) 本质上是基于前面四个 \( K \) 值生成下一个。如果没有 \( CK_ i \),这个生成过程将完全由之前的 \( K \) 值确定,具有高度的“内部对称性”。攻击者可能利用这种对称性推导出密钥之间的关系。引入与轮数 \( i \) 相关的 \( CK_ i \),相当于在每一轮迭代中加入了一个独特的“扰动”或“轮常量”。这使得每一轮生成的轮密钥 \( rk_ i \) 都不同,并且轮密钥之间不存在简单的线性或差分关系,极大地增强了密钥扩展算法的非线性复杂性,是抵抗相关密钥攻击和滑动攻击的关键设计。 CK的设计依据 : 简单、高效、无歧义 :其生成规则 \( (4i+j)* 7 \mod 256 \) 非常简单,计算速度快,无需在算法实现中存储一个大的常量表,可以即时计算,节省存储空间。 伪随机性 :乘法因子7和模256运算,确保了生成的字节序列在统计上看起来是随机的,没有明显的规律。虽然简单,但已足够为每一轮提供一个独特的、不可预测的输入。 可证明性 :这种确定性的、简单的生成方式,便于在算法安全性证明中进行形式化分析。 第四步:总结与关联 现在,让我们将FK和CK的作用串联起来,看它们如何协同工作: 初始化阶段(FK负责) :用户密钥 \( MK \) 进入后,首先用 FK 进行“预处理”,目的是 消除输入密钥的固有弱点 ,为密钥扩展提供一个良好的、无结构性弱点的起始状态 \( (K_ 0, K_ 1, K_ 2, K_ 3) \)。 扩展阶段(CK负责) :在从起始状态迭代生成32个轮密钥的过程中,每一轮都引入一个不同的 CK_ i 作为“轮常量”,目的是 打破迭代过程的内部对称性和线性 ,确保生成的轮密钥之间相互独立、不具相关性,从而抵抗针对密钥扩展算法的各类分析攻击。 简单来说, FK负责“净化”输入的原料(密钥),CK负责“调味”每一步加工过程(迭代) ,两者共同确保了SM4算法最终使用的“调料”(轮密钥)既安全又独特。这种“初始异或常量+轮常量”的设计模式,是许多现代分组密码(如AES)密钥扩展中的常见且有效的安全措施。