关于SIMON加密电路的原理,参考之前发布的博文【SIMON加密算法的原理】
1.总览与电路介绍
1.1 电路总体结构图
1.2 模式配置介绍
SIMON加密算法的分组长度、密钥长度以及必要的参数配置如下图:
本次需要实现的是SIMON 32/64,即分组长度2n=32,密钥长度mn=64,需要进行32轮加密。
2.电路内部模块及代码实现
2.1 移位模块
SIMON加密电路频繁涉及到移位的相关操作,包括循环左移和循环右移,因此单独设计一个模块专门进行移位操作是十分必要的。
首先回顾一下移位操作:>>>(算术右移)>>(逻辑右移)
- 逻辑右移:>>,不考虑符号位,右移一位,左边补零即可;
- 算术右移:>>>,需要考虑符号位,右移一位,若符号位为1,就在左边补1,;否则,就补0。
2.1.1 循环移位的原理
假设位的数据a需要循环右移n位,我们可以根据下面的流程来实现循环移位:
- 将a逻辑右移n位得到b
- 将a逻辑左移(m-n)位得到c
- 将b与c按位相或得到循环右移n位的结果d
d即为所要的移位结果
用代码表示,即为:
temp = (shift_in >> shift_amount) | (shift_in << (WIDTH - shift_amount));//向右循环移位
下图是一个实例,我们要将16位二进制数a=16’b1011101011110000进行循环右移7位,bcd三个数对应上述的流程,1~7对应7次一位循环右移,可以看到,第七次循环右移的结果与d的值完全一致。
2.1.2 移位模块的实现
从而,我们能够编写出移位模块的代码,如下:
module shifter #(parameter WIDTH = 16 //定义字长,即2n中的n,SIMON32/64即字长为16
)
(input logic [WIDTH-1:0] shift_in, //需要移位的字input logic direction, //移位的方向,如果是1则往右移,如果是0往左移input logic [($clog2(WIDTH))-1:0] shift_amount, //移位的位数,由于移位位数的位宽并不固定,需要使用系统函数$clog2动态调整位宽以避免失效//$clog2是Verilog--2005标准新增的一个系统函数,功能就是对输入整数实现以2为底取对数,其结果向上取整(如5.5取6)。output logic [WIDTH-1:0] shift_out //完成移位的字
);logic [WIDTH-1:0] temp ; //via中间变量always_comb beginif (direction == 1'b1) //direction=1,向右循环移位temp = (shift_in >> shift_amount) | (shift_in << (WIDTH - shift_amount));else //direction=0,向左循环移位temp = (shift_in << shift_amount) | (shift_in >> (WIDTH - shift_amount));endassign shift_out = temp;endmodule
注意,为了代码的可复用性,使用到了系统函数$clog2,其功能是动态调整位宽以避免失效,有一篇博文比较详细描述了$clog2,如果想要了解更多,请【点此前往查看该博文】
2.2 轮函数运算模块
轮函数运算模块结构图如下:
一次轮函数运算的流程为:
- 对2n位输入分组长度的数据分成高n位XL和低n位XR
- XL循环左移1位和循环左移8位的数据进行按位与
- 2中得到的数据和XR进行异或
- XL循环左移2位,然后与3中得到的数据进行异或
- 4中得到的数据与相应轮密钥进行异或
- 5中得到的数据对原XL进行更新,原XL数据直接覆盖原XR数据
2.2.1 轮函数运算公式
重复上述1-6的操作直至达到1.2节表中规定的轮数R,即完成1次加密,相应的公式表达如下:
R k ( x , y ) = ( y ⨁ ( S x & S 8 x ) ⨁ S 2 x ⨁ k , x ) R_k(x,y)=(y\bigoplus(Sx\&S^8x)\bigoplus S^2x\bigoplus k,x) Rk(x,y)=(y⨁(Sx&S8x)⨁S2x⨁k,x)
其中: x x x(或 x i + 1 x_{i+1} xi+1)是高 n n n位 X L XL XL; y y y(或 x i x_i xi)是低 n n n位 X R XR XR;
R k R_k Rk是轮函数; S i x S^ix Six表示 x x x循环左移 i i i位; k k k为密钥
2.2.2 轮函数运算模块的实现
首先,我们需要根据需要,调用2.1节的移位模块,计算移位得到的数据,然后根据公式计算出结果,并将结果分别赋给x和y用作下一轮的轮函数运算,相应代码如下:
module round (input logic clk, reset, //时钟和复位信号input logic [15:0] x_in, y_in, key_in, //x_in和y_in是拆成左右两个字的明文,或中间状态,key_in是密钥output logic [15:0] x_out, y_out //x_out和y_out是经过本轮加密的密文
);logic [15:0] S1_sig, S2_sig, S8_sig;logic [15:0] x_temp, y_temp;shifter #(16) S1 (x_in, 1'b0, 4'd1, S1_sig); //调用shifter移位模块,dirt=0表示左移,mount=1表示移动一位,即循环左移一位,结果存入S1shifter #(16) S2 (x_in, 1'b0, 4'd8, S8_sig); //同理shifter #(16) S3 (x_in, 1'b0, 4'd2, S2_sig);always_ff @(posedge clk) beginif (reset) begin //复位操作x_temp <= 16'h00;y_temp <= 16'h00;endelse beginx_temp <= (S1_sig & S8_sig) ^ y_in ^ S2_sig ^ key_in; //对y_in进行运算后赋值给x,当作下一轮的x_iny_temp <= x_in; //将x_in的值赋给y,当作下一轮的y_inendendassign x_out = x_temp;assign y_out = y_temp;endmodule
2.3 密钥调度模块
对特定的 SIMON 2n/mn,密钥调度的方法取决于 m 的取值,m 的 3 种取值对应的具体密钥调度方法有所区别。将输入初始密钥等分为m组,有:
当m=2或3 时
- 对最高n 位循环右移3 位后与低 n 位进行异或得到中间值
- 同时在循环右移3 位的基础上再右移 1 位与上述中间值再次异或
- 最终异或上轮常数的第i位后再异或常量M,并更新密钥寄存器的最高 n 位
- 各组密钥寄存器分别由上一组密钥寄存器的值进行覆盖更新。
当m=4时有所不同。
2.3.1 密钥生成公式
根据前面的介绍,可以得到密钥生成公式如下:
k i + m = { c i ⨁ k i S − 3 ( k i + 1 ) ⊕ S − 4 ( k i + 1 ) , m = 2 ; c i ⨁ k i S − 3 ( k i + 2 ) ⊕ S − 4 ( k i + 2 ) , m = 3 ; c i ⨁ k i ⨁ k i + 1 ⊕ S − 1 ( k i + 1 ) ⊕ S − 3 ( k i + 1 ) ⊕ S − 4 ( k i + 1 ) , m = 4 k_{i+m}=\begin{cases}c_i\bigoplus k_iS^{-3}\left(k_{i+1}\right)\oplus S^{-4}\left(k_{i+1}\right),m=2;\\c_i\bigoplus k_iS^{-3}\left(k_{i+2}\right)\oplus S^{-4}\left(k_{i+2}\right),m=3;\\c_i\bigoplus k_i\bigoplus k_{i+1}\oplus S^{-1}\left(k_{i+1}\right)\oplus\\S^{-3}\left(k_{i+1}\right)\oplus S^{-4}\left(k_{i+1}\right),\quad m=4\end{cases} ki+m=⎩ ⎨ ⎧ci⨁kiS−3(ki+1)⊕S−4(ki+1),m=2;ci⨁kiS−3(ki+2)⊕S−4(ki+2),m=3;ci⨁ki⨁ki+1⊕S−1(ki+1)⊕S−3(ki+1)⊕S−4(ki+1),m=4
其中: x x x是高 n n n位 X L XL XL; y y y是低 n n n位 X R XR XR; R k R_k Rk是轮函数; S i x S^ix Six表示 x x x循环左移 i i i位; k k k为密钥。