SPECK轻量级分组密码算法的轮函数设计
一、算法背景与概述
SPECK是由美国国家安全局(NSA)在2013年提出的一族轻量级分组密码算法,旨在为资源受限环境(如物联网设备、嵌入式系统)提供高效且安全的加密。该算法族包含多个变体,其分组长度和密钥长度可以组合,例如SPECK32/64(分组32位,密钥64位)、SPECK64/128、SPECK128/256等。其核心是一个简洁而高效的轮函数,通过多轮迭代实现混淆和扩散。
二、算法参数与记号
在深入轮函数之前,我们先明确SPECK的基本结构参数:
- 分组大小(\(2n\)位):通常表示为两个字(Word),每个字\(n\)位。例如,SPECK64/128中,\(n=32\),分组为两个32位字\((x, y)\)。
- 密钥大小(\(m*n\)位):通常由\(m\)个\(n\)位字组成。例如,SPECK64/128中,\(m=4\),密钥为4个32位字\((k_0, k_1, k_2, k_3)\)。
- 轮数\(T\):根据具体变体而定,例如SPECK64/128需要27轮。
轮函数是迭代加密的核心,它每轮接受当前的状态(两个\(n\)位字)和一个轮密钥(一个\(n\)位字),并输出新的状态。
三、轮函数设计详解
轮函数的设计遵循ARX(Addition-Rotation-XOR)模式,即只使用模加、循环移位和异或这三种非常高效的运算。这使得SPECK特别适合在软件和硬件上快速实现。
我们设当前轮输入的状态为两个\(n\)位字:\(x_i\)和\(y_i\),其中\(i\)为轮数(从0开始)。设当前轮的轮密钥为\(k_i\)(也是一个\(n\)位字)。则一轮SPECK的加密操作如下:
- 第一步:对第一个字的操作
\[ x_{i+1} = ((x_i \ggg \alpha) \boxplus y_i) \oplus k_i \]
其中:
- \(\ggg \alpha\) 表示向右循环移位\(\alpha\)位(对于所有SPECK变体,\(\alpha = 8\),除了SPECK48中\(\alpha=8\)或\(7\),但主流实现固定为8)。
- \(\boxplus\) 表示模\(2^n\)加法(即普通的\(n\)位整数加法,忽略溢出)。
- \(\oplus\) 表示按位异或。
这一步骤可以分解为:
a. 将\(x_i\)循环右移\(\alpha\)位,得到\(x_i^{>>}\)。
b. 将\(x_i^{>>}\)与\(y_i\)进行模\(2^n\)相加。
c. 将上一步的结果与轮密钥\(k_i\)进行异或。
d. 最终结果作为下一轮状态的第一部分\(x_{i+1}\)。
- 第二步:对第二个字的操作
\[ y_{i+1} = (y_i \lll \beta) \oplus x_{i+1} \]
其中:
- \(\lll \beta\) 表示向左循环移位\(\beta\)位(对于所有SPECK变体,\(\beta = 3\))。
- \(x_{i+1}\)是第一步刚刚计算得到的新值。
这一步骤可以分解为:
a. 将\(y_i\)循环左移\(\beta\)位,得到\(y_i^{<<}\)。
b. 将\(y_i^{<<}\)与第一步得到的\(x_{i+1}\)进行异或。
c. 最终结果作为下一轮状态的第二部分\(y_{i+1}\)。
四、轮函数的逆向思考:解密过程
由于SPECK的轮函数是基于Feistel类结构的变体(但非标准Feistel),其解密过程是加密过程的逆过程。解密时,需要已知轮密钥序列(与加密相同,但逆序使用),并按以下步骤计算:
已知\(x_{i+1}\)和\(y_{i+1}\),求\(x_i\)和\(y_i\):
- 逆向第二步:
由于 \(y_{i+1} = (y_i \lll \beta) \oplus x_{i+1}\),我们可以先恢复出\(y_i \lll \beta\):
\[ y_i \lll \beta = y_{i+1} \oplus x_{i+1} \]
然后对\(y_i \lll \beta\)进行右循环移位\(\beta\)位(因为\(\lll \beta\)的逆是\(\ggg \beta\)),得到:
\[ y_i = (y_{i+1} \oplus x_{i+1}) \ggg \beta \]
- 逆向第一步:
已知 \(x_{i+1} = ((x_i \ggg \alpha) \boxplus y_i) \oplus k_i\)。
首先,恢复出\((x_i \ggg \alpha) \boxplus y_i\):
\[ (x_i \ggg \alpha) \boxplus y_i = x_{i+1} \oplus k_i \]
然后,从这个和中减去\(y_i\)(模\(2^n\)减法,记为\(\boxminus\)):
\[ x_i \ggg \alpha = (x_{i+1} \oplus k_i) \boxminus y_i \]
最后,对\(x_i \ggg \alpha\)进行左循环移位\(\alpha\)位(因为\(\ggg \alpha\)的逆是\(\lll \alpha\)),得到原始的\(x_i\):
\[ x_i = ((x_{i+1} \oplus k_i) \boxminus y_i) \lll \alpha \]
这就完成了一轮的解密。
五、轮密钥的生成(密钥扩展算法)
轮密钥\(k_i\)由一个简洁的密钥扩展算法生成。假设初始密钥由\(m\)个\(n\)位字组成:\((l_0, l_1, ..., l_{m-2}, k_0)\),其中\(l\)序列和\(k\)序列共同构成密钥状态。密钥扩展过程也使用ARX操作,与轮函数结构相似,但参数不同(循环移位位数通常为\(\alpha\)和\(\beta\))。
例如,对于SPECK64/128(\(m=4\)),密钥扩展的递推关系为:
\[l_{i+m-1} = (k_i \boxplus (l_i \ggg \alpha)) \oplus i \]
\[ k_{i+1} = (k_i \lll \beta) \oplus l_{i+m-1} \]
其中\(i\)从0开始,作为轮常量以抵抗对称攻击。生成的\(k_0, k_1, ..., k_{T-1}\)依次作为轮密钥使用。这种设计使得密钥扩展与轮函数共享逻辑,进一步简化了实现。
六、设计特点与安全性
- 简洁性:轮函数仅由模加、循环移位、异或组成,没有复杂的S盒,易于在软硬件上高效实现。
- 扩散性:模加和循环移位的组合,使得单比特的输入变化能在几轮内扩散到整个状态。
- 安全性:设计者经过充分的安全性分析,能抵抗差分攻击、线性攻击等。所需的轮数(如SPECK64/128为27轮)提供了足够的安全边际。
通过以上循序渐进的分析,你应该能清晰地理解SPECK轮函数的核心设计思想、每一步的运算细节,以及它如何通过迭代实现安全的加密与解密。