关于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 begin
if (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));
end
assign 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表示移动一位,即循环左移一位,结果存入S1
shifter #(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) begin
if (reset) begin //复位操作
x_temp <= 16'h00;
y_temp <= 16'h00;
end
else begin
x_temp <= (S1_sig & S8_sig) ^ y_in ^ S2_sig ^ key_in;
//对y_in进行运算后赋值给x,当作下一轮的x_in
y_temp <= x_in;
//将x_in的值赋给y,当作下一轮的y_in
end
end
assign 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为密钥。