前言:
Twofish 的核心特点是块大小为 128 位,支持 128、192 或 256 位的密钥,并且采用了 Feistel 网络结构。

算法流程
密钥扩展:
Twofish 的密钥扩展 (Key Schedule) 是该算法最复杂、设计最精妙的部分。它不仅负责生成每一轮需要的子密钥(Subkeys),还负责生成依赖于密钥的 S-box。
整个过程可以分为三个主要部分:
初始化向量生成(将主密钥分为
和 向量)。 子密钥生成(生成 40 个用于白化和轮函数的密钥)。
记为
密钥相关的 S-box 生成。
由于逆向时重点不在这里,简单带过就可
输入白化:
因为加密前的plain text是128 bits,也就是16 bytes。假设这16 bytes分别是p0, … ,p15。将p0, … ,p15分为4组:P(i) = ∑p(4i+j)2^(8j),其中i,j = 0, ... ,3
算法将这 16 个字节按顺序每 4 个一组,分配给 4 个字
(Word 0): 对应字节 (Word 1): 对应字节 (Word 2): 对应字节 (Word 3): 对应字节
然后进行运算R(0,i) = P(i) xor K(i),其中i = 0, ... ,3
开始核心运算(循环16次):
每一轮 (
Step A: g 函数处理 (非线性层)
利用左侧的两个字
和 作为输入。 直接进入 函数。 先左移 8 位 ( ROL 8),再进入函数。 _
函数内部:_ 字节通过 密钥相关的 S-box 替换,然后乘以 MDS 矩阵 进行扩散。
Step B: PHT 变换 (混合层)
将两个
函数的输出 ( ) 进行伪阿达马变换。 混合出两个新值,并分别加上本轮的子密钥 (
)。得到 和 。
Step C: 交叉加密 (Feistel Cross)
利用生成的
去加密右边的 : 先与 异或,然后右移 1 位 ( ROR 1)。
利用生成的
去加密右边的 : 先左移 1 位 ( ROL 1),然后与异或。
Step D: 交换 (Swap)
- 除了最后一轮,每轮结束后,左边两个字 (
) 与右边处理后的两个字 ( ) 交换位置。
伪代码
这里假设密钥长度为 128-bit (
1 | # 假设 R 是一个包含 4 个 32-bit 字的数组: R[0], R[1], R[2], R[3] |
其中用到的g函数
1 | # 输入: |
g函数中的依赖函数S-box
1 | # 输入: |
g函数中的依赖函数MDS 矩阵乘法
1 | # 输入: 4 个 8-bit 字节 (y0, y1, y2, y3) |
g函数中的有限域乘法 (GF Mult)
用于 MDS 矩阵计算。多项式 0x169。
1 | # 输入: a, b (两个 8-bit 字节) |
这就是 g 函数完整的调用链: g s_box_logic (查 q 表, XOR S 向量) mds_multiply gf_mult (底层位运算)。
输出白化:
16 轮结束后(注意最后一轮不交换,或者说交换回来),再次与
输出: 拼合 4 个字得到 128-bit 密文。
Feistel 结构的经典特征
Twofish 采用的是一种略微修改的 Feistel 结构。要理解它为什么这么设计,必须理解 Feistel 网络 的核心哲学。
Feistel 结构由 Horst Feistel 在 1970 年代提出(DES 算法是其代表作),它是对称加密中最具统治力的设计模式之一。
核心特征:构造无需可逆 (Invertibility is not required for F)
这是 Feistel 结构最天才的地方,也是它最大的特征。
原理: 在 Feistel 结构中,
。 解释: 无论中间的轮函数
有多么复杂、多么混乱、甚至不可逆(例如, 可以是一个不可逆的哈希函数,或者是像 Twofish 这种复杂的 MDS 变换),整个加密算法依然是可逆的。 解密: 解密过程只需要完全复用加密的电路/代码,唯一的区别是子密钥的使用顺序倒过来(从
用到 )。 Twofish 的体现: 它的
函数里有复杂的模运算和矩阵乘法,如果没有 Feistel 结构,想逆向推导 函数的输入是非常困难的。但得益于 Feistel 结构,解密时我们不需要逆向计算 ,只需要重新生成一遍 值然后异或回去即可。
“分治”策略 (Divide and Conquer)
特征: 数据总是被分成两半(Left 和 Right)。
操作: 每一轮只处理其中一半数据,另一半数据保持不变(或者作为“原版”参考)。
Twofish 的体现: 它把 128 位分成 4 个 32 位字。每一轮实际上是利用左边的 64 位(
)去加密右边的 64 位( )。
结构对称性 (Structural Symmetry)
特征: 加密和解密的硬件电路或软件代码几乎完全相同。
优势: 这极大地降低了硬件实现的成本(芯片面积减半)和软件代码的大小。
Twofish 的体现: 你写好了一个
Encrypt函数,要写Decrypt函数时,逻辑几乎不用动,只需要把轮密钥的索引倒序,并在最后处理一下 ROL/ROR 的方向即可。
轮数迭代带来的安全性 (Avalanche Effect)
特征: 单独一轮的 Feistel 往往也是弱的(因为有一半数据没变)。但是,通过多轮迭代(Round Iteration)和每一轮结束后的交换 (Swap),可以让左边的数据跑到右边去被处理,右边的数据跑到左边去充当输入。
效果: 经过足够多的轮数(如 16 轮),输入的每一个 bit 都会影响到输出的每一个 bit(雪崩效应)。
代码加密解密
twofish.h
1 |
|
table.h
1 |
|
twofish.c
1 |
|
魔改点
rsm函数,0x14d可替换为其他数字(
0x14d(关键常数):这是 RS 码生成所使用的 本原多项式 (Primitive Polynomial)。
对应数学公式:
。)
- Twofish_generate_ext_s_keys函数中gf的参数0x166可替换
- Twofish_mds_mul函数中gf的参数0x166可替换
reference:
- 本文链接: http://example.com/2026/01/27/逆向中的密码学/Twofish逆向/
- 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
欢迎关注我的其它发布渠道