SM4分组密码算法的Feistel结构与轮函数F详解
题目描述
讲解SM4分组密码算法中采用的Feistel网络结构如何工作,并深入剖析其核心组件——轮函数F的具体设计步骤,包括其中的非线性变换τ、线性变换L、以及与轮密钥的相互作用。目标是理解SMistel结构如何确保算法的可逆性(加解密相似),以及轮函数F如何提供混淆和扩散。
解题过程/讲解
SM4是一种分组长度为128位、密钥长度为128位的分组密码算法。它采用了Feistel网络结构,这是一种经典的对称密码设计结构,以其加解密过程相似而著称,能简化硬件实现。
第一步:理解Feistel网络的基本框架
在Feistel网络中,每一轮(Round)的处理都遵循相同的模式。对于SM4,其分组是128位,我们将它分为4个32位的字(Word)。
- 初始输入分组:将128位的明文输入记作 \((X_0, X_1, X_2, X_3)\),其中每个 \(X_i\) 是32位。
- 基本迭代公式:SM4进行32轮完全相同的迭代操作。其核心迭代公式(对于第 \(i\) 轮, \(i\) 从 0 到 31)是:
\[ X_{i+4} = F(X_i, X_{i+1}, X_{i+2}, X_{i+3}, rk_i) = X_i \oplus T(X_{i+1} \oplus X_{i+2} \oplus X_{i+3} \oplus rk_i) \]
其中:
* $ X_i, X_{i+1}, X_{i+2}, X_{i+3} $ 是当前轮四个32位的输入字。
* $ rk_i $ 是第 $ i $ 轮的32位轮密钥。
* $ T $ 是一个可逆的合成变换,是轮函数F的核心。
* $ \oplus $ 表示32位字的按位异或(XOR)操作。
- 结构图解:你可以想象一个“流水线”或“滑动窗口”。每一轮生成一个新的字 \(X_{i+4}\),然后窗口向后滑动一个位置,用 \((X_{i+1}, X_{i+2}, X_{i+3}, X_{i+4})\) 作为下一轮的输入。经过32轮后,我们得到最终的128位输出 \((X_{32}, X_{33}, X_{34}, X_{35})\),但在最终输出前,会进行一个反序变换 \(R\) :输出为 \((X_{35}, X_{34}, X_{33}, X_{32})\)。
第二步:剖析轮函数F的核心——合成变换T
迭代公式中的 \(T\) 函数是关键,它定义为 \(T(\cdot) = L(\tau(\cdot))\),即先进行非线性变换 \(\tau\),再进行线性变换 \(L\)。我们一步步看。
步骤1:与轮密钥结合(异或运算)
首先计算一个中间值 \(B\):
\[B = X_{i+1} \oplus X_{i+2} \oplus X_{i+3} \oplus rk_i \]
这里,我们将轮密钥 \(rk_i\) 与当前状态中的三个字进行异或。这是轮函数F的“输入混合”步骤,将密钥材料引入。
步骤2:非线性变换 \(\tau\)
将上一步得到的32位字 \(B\) 分成4个8位的字节:\(B = (b_0, b_1, b_2, b_3)\)。
然后,并行地对每个字节进行S盒替换。SM4的S盒是一个固定的8位输入、8位输出的非线性置换表(通常用16x16的矩阵表示,查表实现)。
\[(b'_0, b'_1, b'_2, b'_3) = (Sbox(b_0), Sbox(b_1), Sbox(b_2), Sbox(b_3)) \]
得到的 \(B' = (b'_0, b'_1, b'_2, b'_3)\) 是一个新的32位字。这个变换 \(\tau\) 提供了算法的非线性混淆特性,是抵抗线性密码分析和差分密码分析的核心。
步骤3:线性变换 \(L\)
对非线性变换的输出 \(B'\) 应用一个线性变换 \(L\)。这个变换是一个固定的线性运算,旨在提供良好的扩散效果。其定义如下:
\[L(B') = B' \oplus (B' <<< 2) \oplus (B' <<< 10) \oplus (B' <<< 18) \oplus (B' <<< 24) \]
其中 \(<<< n\) 表示将32位字循环左移 \(n\) 位。这个操作是将 \(B'\) 与其自身的几个循环移位版本进行异或。因为异或是线性运算,组合起来 \(L\) 也是一个线性变换。它确保了输入 \(B'\) 中的一个比特的变化,会影响输出 \(L(B')\) 中的多个比特,且这种影响在多轮迭代后迅速扩散到整个分组。
步骤4:完成轮函数F的输出
最后,将原始的 \(X_i\) 与 \(T\) 函数的输出(即 \(L(\tau(B))\))进行异或,得到本轮的新字 \(X_{i+4}\):
\[X_{i+4} = X_i \oplus T(B) = X_i \oplus L(\tau(B)) \]
注意,\(X_{i+1}, X_{i+2}, X_{i+3}\) 这三个字在本轮中并未被直接修改,它们只是“参与”了计算,然后被原封不动地“传递”到下一轮作为一部分输入。 这就是Feistel结构的精妙之处之一。
第三步:理解Feistel结构的可逆性(解密过程)
解密过程与加密过程完全相同,唯一的区别是轮密钥的使用顺序相反。
- 加密时,使用轮密钥序列 \((rk_0, rk_1, ..., rk_{31})\)。
- 解密时,使用轮密钥序列 \((rk_{31}, rk_{30}, ..., rk_0)\)。
为什么这样可行?
我们观察加密的迭代公式:\(X_{i+4} = X_i \oplus T(X_{i+1} \oplus X_{i+2} \oplus X_{i+3} \oplus rk_i)\)。
如果我们从最后一轮的输出 \((X_{35}, X_{34}, X_{33}, X_{32})\) 开始,并希望回推到 \((X_0, X_1, X_2, X_3)\),我们可以从公式反解出 \(X_i\):
\[X_i = X_{i+4} \oplus T(X_{i+1} \oplus X_{i+2} \oplus X_{i+3} \oplus rk_i) \]
这个公式和加密公式形式一模一样!这意味着,如果我们已知 \(X_{i+1}, X_{i+2}, X_{i+3}, X_{i+4}\) 和正确的 \(rk_i\),就能算出 \(X_i\)。在解密时,我们反向迭代(i 从 31 到 0),并将对应的轮密钥 \(rk_i\) 代入,就能一步步恢复出原始的 \(X_0, X_1, X_2, X_3\)。最后同样需要进行一个反序变换 \(R\) 得到正确的明文顺序。
总结
SM4的Feistel结构与轮函数F共同保障了其安全性:
- Feistel结构:保证了算法设计简单、加解密过程高度对称(仅轮密钥顺序不同),易于硬件和软件实现。
- 轮函数F:
- 异或混合:将当前状态与轮密钥结合。
- S盒(τ):提供核心的非线性混淆,抵抗线性/差分分析。
- 循环移位异或(L):提供快速的比特扩散,确保雪崩效应。
- 多轮迭代:通过32轮这样的操作,将单个S盒的局部非线性效应和L变换的扩散效应充分传播到整个128位数据块中,形成了强大的整体密码强度。