本文基于FPGA实现高速SM4加密与解密,提供开源Verilog RTL设计和可综合工程:https://github.com/cassuto/SM4-FPGA。
一、国密标准概述
国家密码局制定了一系列密码学算法,包括SM1/2/3/4等,其中SM2是椭圆曲线公钥密码算法,SM3是密码杂凑算法,SM4是分组加密算法。
上述算法的现行标准如下。标准原文可在“国家标准全文公开系统”查询。
-
SM2:
GB/T 32918系列标准:
《GB/T 32918.1-2016 SM2椭圆曲线公钥密码算法 第1部分:总则》
《GB/T 32918.2-2016 SM2椭圆曲线公钥密码算法 第2部分:数字签名算法》
《GB/T 32918.3-2016 SM2椭圆曲线公钥密码算法 第3部分:密钥交换协议》
《GB/T 32918.4-2016 SM2椭圆曲线公钥密码算法 第4部分:公钥加密算法》
《GB/T 32918.5-2017 SM2椭圆曲线公钥密码算法 第5部分:参数定义》 -
SM3:
《GB/T 32905-2016 SM3密码杂凑算法》 -
SM4:
《GB/T 32907-2016 SM4分组密码算法》
SM1算法并未公开。
二、SM4简介
SM4算法是分组加密算法,分组长度和密钥长度均为128bit。SM4算法由密钥扩展算法与加密(解密)算法两部分构成,均采用非线性迭代结构;加密与解密算法具有相同的结构,只是对输入轮密钥进行反序变换。
2.1 密钥
密钥长度为128bit,用\(MK=({MK}_0,{MK}_1, {MK}_2,{MK}_3)\)表示,其中向量\({MK}_i \space (i=0,1,2,3)\)表示一个字(32bit)。
例如密钥\(\text{0x} \space 01 \space 23 \space 45 \space 67 \space 89 \space AB \space CD \space EF \space FE \space DC \space BA \space 98 \space 76 \space 54 \space 32 \space 10\)对应的\(MK\)为:
其中\({MK}_0=\begin{bmatrix} 01 & 23 & 45 & 67 \end{bmatrix}^T\)。
2.2 密钥扩展算法
密钥扩展算法用于生成轮密钥,轮密钥用于加密算法每轮非线性迭代的输入。轮密钥用\(({rk}_1,{rk}_2, \dots , {rk}_{31})\)表示,其中向量\({rk}_i \space (i=0, \dots ,31)\)为一个字,表示第\(i\)轮迭代所使用的轮密钥。
在介绍密钥扩展算法之前,需要引入轮函数和合成置换函数。
2.2.1 轮函数
设轮函数输入为\((X_0,X_1,X_2,X_3)\),轮密钥为\(rk \in Z\),轮函数定义为:
2.2.2 合成置换函数
T函数由一个非线性变换和线性变换构成。其中非线性变换函数通过查找表(S盒)确定。设32bit输入为\(A=(a_0,a_1,a_2,a_3)\),输出为\(B=(b_0,b_1,b_2,b_3)\),其中分量\(a_i,b_i \space (i=0, \dots 3)\)是一个字节,非线性变换表示为:
每个S盒都是\(16 \times 16\)的查找表,具体取值见附录C。
经过S盒置换后,再进行如下线性变换。设输入为B,输出为C,定义线性变换\(L\):
2.2.3 密钥扩展算法
其中\({CK}_i\)、\({FK}_i\)都是常量,具体取值见附录A、B。将合成置换函数\(T\)中的线性变换\(L\)替换为\(L\'(B)=B \oplus (B<<13) \oplus (B<<23)\),就得到了\(T\'\)函数。
上述每一步迭代的数据流如下图所示:
第\(i\)、\(i+1\)、\(i+2\)、\(i+3\)步迭代的输出将作为第\(i+4\)步迭代的输入,具体可参考下图:
从总体看,轮密钥是以密钥为唯一变量的函数,若密钥已经确定,则轮密钥也是确定的。因此当密钥固定不变时,轮密钥可以预先计算。
2.3 反序变换
设反序变换的输入为\(A=(a_0,a_1,a_2,a_3)\),输出为\(B=(b_0,b_1,b_2,b_3)\),反序变换定义为:
2.4 加密算法
设明文输入为\((X_3,X_2,X_1,X_0)\),密文输出为\((Y_0,Y_1,Y_2,Y_3)\),密码扩展算法输出轮密钥为\(rk\),则加密算法由如下步骤完成:
(1)非线性迭代
数据流图如下所示:
(2)输出
2.5 解密算法
解密算法与加密算法结构相同,只是对轮密钥反序变换后再使用,即使用\(rk\'=({rk}_{31},{rk}_{30}, \dots ,{rk}_0)\)作为轮密钥。
三、实现
根据上文得出的数据流图,容易导出硬件实现。
3.1 流水线总体结构
SM4加密算法核心是32轮非线性迭代,在硬件上,可通过组合逻辑块来实现每轮迭代,第\(i\)个组合逻辑块的输出作为第\(i+1\)个组合逻辑块的输入,得到如下所示的非流水线实现:
这种设计在低速时钟下诚然可以正确工作,但关键路径已经很长,进一步提升时钟频率变得困难。
解决办法是采用流水线,通过寄存器划分关键路径。设每个组合逻辑块的延时为\(d_i \space (i=0,1, \dots ,31)\),非流水线实现中,关键路径的数据传输延时为\(D=\sum_{i=0}^{31}d_i\),而流水线实现中关键路径的数据传输延时为\(D\'=\max_{0 \le i \le 31}d_i + T_{cko}\)。可知\(D\'\lt D\),时序得到了改善。
设流水线时钟频率为\(F\),则系统的峰值吞吐率\(T_{max}\)可计算为:
当时钟频率\(F=100MHz\)时,峰值吞吐率\(T_{max}\)可达\(12.8Gbps\)。
考虑流水线停顿(stall)对流水线效率造成的影响。若流水线效率为\(0 \lt \eta \le 1\),则实际吞吐率为:
3.2 行为级模型的建立
通过高级语言(这里采用C++)建立算法的行为级模型,这里只贴出关键代码。完整代码请参考Github仓库。
合成置换函数\(T\):
/* Transformation function */
uint32_t T(uint32_t x) {
uint32_t B = sbox(x);
return B ^ rol(B, 2) ^ rol(B, 10) ^ rol(B, 18) ^ rol(B, 24);
}
合成置换函数\(T\'\)
/* Transformation inverse function */
uint32_t T_1(uint32_t x) {
uint32_t B = sbox(x);
return B ^ rol(B, 13) ^ rol(B, 23);
}
密钥扩展算法:
void keyexpand(const uint8_t *mk, uint32_t K[36]) {
K[0] = btw(mk) ^ FK[0];
K[1] = btw(mk+4) ^ FK[1];
K[2] = btw(mk+8) ^ FK[2];
K[3] = btw(mk+12) ^ FK[3];
for(int i=0; i<32; i++) {
K[i+4] = K[i] ^ T_1(K[i+1] ^ K[i+2] ^ K[i+3] ^ CK[i]);
}
}
加密/解密算法:
void decenc(bool enc, const uint8_t *in, uint8_t *out, uint32_t K[36]) {
unsigned long X[36] = {0};
X[0] = btw(in);
X[1] = btw(in+4);
X[2] = btw(in+8);
X[3] = btw(in+12);
for(int i = 0; i<32; i++) {
X[i+4] = X[i] ^ T(X[i+1] ^ X[i+2] ^ X[i+3] ^ K[enc ? i+4 : 35-i]);
}
wtb(X[35], out);
wtb(X[34], out+4);
wtb(X[33], out+8);
wtb(X[32], out+12);
}
建立的行为级模型可为仿真验证提供依据,通过对比FPGA计算结果与行为级模型的计算结果,可检验FPGA实现是否正确。
3.3 RTL模型的建立
3.3.1 S盒替换的实现
S盒置换用于合成置换函数\(T\)。S盒置换函数是32bit字到32bit字的映射,按照字节粒度逐字节替换。
通过ROM实现S盒函数。将输入字节\(a_0,a_1,a_2,a_3\)作为ROM的地址,将ROM的数据输出作为S盒函数的值。输入4个字节的替换是并行的。
3.3.2 流水级的实现
流水级实现轮函数。轮函数的基本框架是异或门;合成置换函数\(T\)的非线性变换函数由ROM实现;流水线的数据暂存和传输通过寄存器实现。
\(L\)为合成置换函数\(T\)的线性变换函数,具体可参见Verilog源码,这里不再赘述。
3.3.3 顶层模块的实现
信号名称 | 描述 |
---|---|
CLK_i | 时钟输入 |
RST_N_i | 异步复位输入(下降沿有效) |
MK_i | 128bit密钥输入 |
MK_VALID_i | 密钥输入是否有效 |
DAT_i | 128bit明文(密文)分组输入 |
DAT_VALID_i | 分组输入是否有效 |
DAT_o | 128bit密文(明文)分组输出 |
DAT_READY_o | 分组输出是否有效 |
顶层模块内部RTL原理图
其中keyexp模块实现密钥扩展算法,decenc模块实现加密/解密非线性迭代算法。
3.3.4 顶层模块的参数化
通过可变参数实现顶层模块的可配置性。顶层模块既可以实现分组加密,又可以实现分组解密。此外,还可配置成使用固定轮密钥,从而省去keyexp模块的资源。
参数名 | 描述 | 默认值 |
---|---|---|
MODE | 0:加密; 非0:解密 | |
ENABLE_FIXED_RK | 0:不使用固定轮密钥;非0:使用固定轮密钥 | 0 |
FIXED_RK | 若使用固定轮密钥,指定1024bit轮密钥 | 128’h0 |
注:当ENABLE_FIXED_RK!=0时,采用FIXED_RK指定的轮密钥,外部输入信号MK_i和MK_VALID_i将被忽略,此时模块占用逻辑资源最少;否则,采用MK_i指定的密钥,轮密钥将动态生成。
四、FPGA验证
在Xilinx ZYNQ-7010平台构建如下基于ILA(集成逻辑分析仪)的测试环境,验证SM4模块。
通过ILA抓取加密模块与解密模块输入输出信号波形,验证其功能。
输入明文分组:128\'h \(01 \space 23 \space 45 \space 67 \space 89 \space AB \space CD \space EF \space FE \space DC \space BA \space 98 \space 76 \space 54 \space 32 \space 10\)
输入密钥为:128\'h \(01 \space 23 \space 45 \space 67 \space 89 \space AB \space CD \space EF \space FE \space DC \space BA \space 98 \space 76 \space 54 \space 32 \space 10\)
加密模块输出密文:ciphertext = 128\'h \(68 \space 1e \space df \space 34 \space d2 \space 06 \space 96 \space 5e \space 86 \space b3 \space e9 \space 4f \space 53 \space 6e \space 42 \space 46\)
解密模块输出明文为:DAT_o = 128\'h \(01 \space 23 \space 45 \space 67 \space 89 \space AB \space CD \space EF \space FE \space DC \space BA \space 98 \space 76 \space 54 \space 32 \space 10\)
结果正确。
4.1 资源占用
4.2 时序(\(Fclk=100MHz\))
计算得出理论最大工作频率\(F_{max} = \frac{1}{T-WNS} = 130 MHz\)
4.3 功耗
附录A:CK参数常量表
\({CK}_0\) | \({CK}_1\) | \({CK}_2\) | \({CK}_3\) |
---|---|---|---|
0x00070E15 | 0x1C232A31 | 0x383F464D | 0x545B6269 |
\({CK}_4\) | \({CK}_5\) | \({CK}_6\) | \({CK}_7\) |
---|---|---|---|
0x70777E85 | 0x8C939AA1 | 0xA8AFB6BD | 0xC4CBD2D9 |
\({CK}_8\) | \({CK}_9\) | \({CK}_{10}\) | \({CK}_{11}\) |
---|---|---|---|
0xE0E7EEF5 | 0xFC030A11 | 0x181F262D | 0x343B4249 |
\({CK}_{12}\) | \({CK}_{13}\) | \({CK}_{14}\) | \({CK}_{15}\) |
---|---|---|---|
0x50575E65 | 0x6C737A81 | 0x888F969D | 0xA4ABB2B9 |
\({CK}_{16}\) | \({CK}_{17}\) | \({CK}_{18}\) | \({CK}_{19}\) |
---|---|---|---|
0xC0C7CED5 | 0xDCE3EAF1 | 0xF8FF060D | 0x141B2229 |
\({CK}_{20}\) | \({CK}_{21}\) | \({CK}_{22}\) | \({CK}_{23}\) |
---|---|---|---|
0x30373E45 | 0x4C535A61 | 0x686F767D | 0x848B9299 |
\({CK}_{24}\) | \({CK}_{25}\) | \({CK}_{26}\) | \({CK}_{27}\) |
---|---|---|---|
0xA0A7AEB5 | 0xBCC3CAD1 | 0xD8DFE6ED | 0xF4FB0209 |
\({CK}_{28}\) | \({CK}_{29}\) | \({CK}_{30}\) | \({CK}_{31}\) |
---|---|---|---|
0x10171E25 | 0x2C333A41 | 0x484F565D | 0x646B7279 |
附录B:FK参数常量表
\({FK}_0\) | \({FK}_1\) | \({FK}_2\) | \({FK}_3\) |
---|---|---|---|
0xA3B1BAC6 | 0x56AA3350 | 0x677D9197 | 0xB27022DC |
附录C:S盒常量表
(表格较长,请拖动下方滚动条查看)
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0xD6 | 0x90 | 0xE9 | 0xFE | 0xCC | 0xE1 | 0x3D | 0xB7 | 0x16 | 0xB6 | 0x14 | 0xC2 | 0x28 | 0xFB | 0x2C | 0x05 |
1 | 0x2B | 0x67 | 0x9A | 0x76 | 0x2A | 0xBE | 0x04 | 0xC3 | 0xAA | 0x44 | 0x13 | 0x26 | 0x49 | 0x86 | 0x06 | 0x99 |
2 | 0x9C | 0x42 | 0x50 | 0xF4 | 0x91 | 0xEF | 0x98 | 0x7A | 0x33 | 0x54 | 0x0B | 0x43 | 0xED | 0xCF | 0xAC | 0x62 |
3 | 0xE4 | 0xB3 | 0x1C | 0xA9 | 0xC9 | 0x08 | 0xE8 | 0x95 | 0x80 | 0xDF | 0x94 | 0xFA | 0x75 | 0x8F | 0x3F | 0xA6 |
4 | 0x47 | 0x07 | 0xA7 | 0xFC | 0xF3 | 0x73 | 0x17 | 0xBA | 0x83 | 0x59 | 0x3C | 0x19 | 0xE6 | 0x85 | 0x4F | 0xA8 |
5 | 0x68 | 0x6B | 0x81 | 0xB2 | 0x71 | 0x64 | 0xDA | 0x8B | 0xF8 | 0xEB | 0x0F | 0x4B | 0x70 | 0x56 | 0x9D | 0x35 |
6 | 0x1E | 0x24 | 0x0E | 0x5E | 0x63 | 0x58 | 0xD1 | 0xA2 | 0x25 | 0x22 | 0x7C | 0x3B | 0x01 | 0x21 | 0x78 | 0x87 |
7 | 0xD4 | 0x00 | 0x46 | 0x57 | 0x9F | 0xD3 | 0x27 | 0x52 | 0x4C | 0x36 | 0x02 | 0xE7 | 0xA0 | 0xC4 | 0xC8 | 0x9E |
8 | 0xEA | 0xBF | 0x8A | 0xD2 | 0x40 | 0xC7 | 0x38 | 0xB5 | 0xA3 | 0xF7 | 0xF2 | 0xCE | 0xF9 | 0x61 | 0x15 | 0xA1 |
9 | 0xE0 | 0xAE | 0x5D | 0xA4 | 0x9B | 0x34 | 0x1A | 0x55 | 0xAD | 0x93 | 0x32 | 0x30 | 0xF5 | 0x8C | 0xB1 | 0xE3 |
A | 0x1D | 0xF6 | 0xE2 | 0x2E | 0x82 | 0x66 | 0xCA | 0x60 | 0xC0 | 0x29 | 0x23 | 0xAB | 0x0D | 0x53 | 0x4E | 0x6F |
B | 0xD5 | 0xDB | 0x37 | 0x45 | 0xDE | 0xFD | 0x8E | 0x2F | 0x03 | 0xFF | 0x6A | 0x72 | 0x6D | 0x6C | 0x5B | 0x51 |
C | 0x8D | 0x1B | 0xAF | 0x92 | 0xBB | 0xDD | 0xBC | 0x7F | 0x11 | 0xD9 | 0x5C | 0x41 | 0x1F | 0x10 | 0x5A | 0xD8 |
D | 0x0A | 0xC1 | 0x31 | 0x88 | 0xA5 | 0xCD | 0x7B | 0xBD | 0x2D | 0x74 | 0xD0 | 0x12 | 0xB8 | 0xE5 | 0xB4 | 0xB0 |
E | 0x89 | 0x69 | 0x97 | 0x4A | 0x0C | 0x96 | 0x77 | 0x7E | 0x65 | 0xB9 | 0xF1 | 0x09 | 0xC5 | 0x6E | 0xC6 | 0x84 |
F | 0x18 | 0xF0 | 0x7D | 0xEC | 0x3A | 0xDC | 0x4D | 0x20 | 0x79 | 0xEE | 0x5F | 0x3E | 0xD7 | 0xCB | 0x39 | 0x48 |
转载请注明出处:https://www.cnblogs.com/the-wind/p/14335632.html,谢谢合作!