avatar

ZUC算法

ZUC算法

由于在看ZUC算法的时候会有很多的字符等符号不太知道于是!

运算符

+ 算术加法运算
ab 整数a和b的乘积
= 赋值操作符
mod 整数模运算
⊕ 按比特位逐位异或运算
田 模2加法运算
‖ 字符串或字节串连接符
下标H 取字的最高16比特
下标L 取字的最低16比特
<<<k 32比特字循环左移k位
>>k 32比特字右移K位
a->b 向量a赋值给向量b,即按分量逐分量赋值

符号

S1,S2,S3,……S15 线性反馈移位寄存器的16个31比特寄存器单元变量
X1,X2,X3,X4 比特重组输出的4个32比特字
R1,R2 非线性函数F的2个32比特记忆单元变量
W 非线性函数F输出的32比特字
W1 R1与X1进行模2^32加法运算输出的32比特字
W2 R2与X2按比特位逐位异或运算输出的32比特字
Z 算法每个节拍输出的32比特密钥字
K 初始种子密钥
IV 初始向量
D1,D2,D3……D15 15比特的字符串常量
F 非线性函数
L 输出密钥字长度

线性反馈移位寄存器(LFSR)

由于这个算法涉及到了LFSR,于是翻起了自己深入浅出密码学,复习一下知识点
定义:一个LFSR由若干时钟存储元件(触发器)和一个反馈路径组成,存储元件的数目给出了LFSR的度,一个拥有m个触发器的LFSR可以称为“度为m”,反馈网络计算移位寄存器中某些触发器的XOR的和,并将其作为上一个触发器的输入

简单LFSR

upload successful
书上的例子挺好的,可以帮助理解LFSR,给了初始状态(S2=1,S1=0,S0=0)
看图:用自己话理解了一下,将S0与S1进行XOR,出来的结果给S3,这时候S0输出出去,S1,S2进行左平移,S3加入S2的位置,依次类推,因为是异或且每次是一位0和1那么可以写成公式就是:S3=S1+S0 mod 2
那我们看一下LFSR的状态序列
upload successful
推导:S(i+3)=S(i)+S(i+1) mod 2
我们可以看到在第6个时钟周期后开始重复,0010111,意味着LFSR输出的周期长度为7

LFSR的数学描述

继续调用了书上的图
upload successful
我们可以看到,LFSR拥有了m个触发器和m个可能的反馈位置,并且这些触发器和反馈的位置之间通过XOR操作连接,看是否活跃取决于反馈系数P0…Pn
这里有了个定义:
如果Pi=1,此反馈是活跃的(即关闭了开关)
如果Pi=0,对应的触发器的输出将不会被反馈(即打开了开关)
将触发器的i的输出与对应的系数Pi相乘,如果Pi=1那么结果就是输出值(对应关闭开关),如果Pi=0,则输出值也为0(即打开开关)即公式:
upload successful
upload successful
即满足了依次左移的原则,更新Sm,则输出序列描述为:
upload successful
因为m位状态向量只能得到2^m -1个非零状态(自己理解为是可能性最后遍历回来),比如最大长度输出序列的LFSR,给定一个度m=4,反馈路径为(P3=0,P2=0,P1=1,P0=1),周期为2^4-1=15;非最大长度输出序列,给定一个度m=4,反馈路径为(P3=1,P2=1,P1=1,P0=1)周期为5

0 0 1 1/0 0 0 1/1 0 0 0/0 1 0 0/0 0 1 0/1 0 0 1/1 1 0 0/0 1 1 0/1 0 1 1/0 1 0 1/1 0 1 0/1 1 0 1/1 1 1 0/1 1 1 1/0 1 1 1/(0 0 1 1)所以为15
1 1 1 1/0 1 1 1/1 0 1 1/1 1 0 1/1 1 1 0/(1 1 1 1 )所以为5
LFSR通常用:反馈系数向量(Pm-1,…,P1,P0)则P(x)=X^m+Pm-1X^m-1+…+P1x+p0
如上面的例子中的系数(P3=0,P2=0,P1=1,P0=1)的LFSR可以表示为多项式x^4+x+1,最大长度LFSR拥有所谓的本源多项式(设f(x)是一个整系数多项式, 若f(x)的系数的公因子只有±1, 则称f(x)是一个本原多项式.)查了很久总结一下:代数式系数对应的0 1 字串,满足,用8进制变为对应的十进制,若为素数,则为本原多项式,所以本原多项式是一种特殊的不可约分多项式,只有1和他的本身.所以例如(0,2,5)为1+x^2+x^5为10011八进制为23为素数
upload successful

算法构架

upload successful
上层是16级线性反馈移位寄存器(LFSR),中层是比特重组(BR),下层是非线性函数F

第一层:线性反馈移位寄存器(LFSR)

upload successful
LFSR包括16个31比特寄存器单元变量S1,S2,S3,……S15,最开始进行了初始化
upload successful
upload successful因为是mod(2^31-1) 2^31-1=2147483647为素数,所以为素域,采用16次本原多项式P(x)=x^16-2^15*x^15-2^17*x^13-2^21*x^10-2^20*x^4-(2^8+1)所以根据线性反馈移位寄存器的公式来说(看上面的介绍)V=2^15*S^15-2^17*S^13-2^21*S^10-2^20*S^4-(2^8+1)S0 mod(2^31-1)先放到一边,准备开始移位即:(s1,s2…s16)变为(s0,s1…s16)所以输出的为32位比特,但是我们要舍去一个最开始的把s16进行放入到s15的位置s0的位置进行保存
所以可以得到公式为是:S16=(V+u)mod(2^31-1)其中v是上面公式得到的与LFSR接受的31比特进行相加之后与2^31-1进行求余就是S16,如果我们的S16=0 那么S16置为2^31-1
以上是初始化的模式,初始化和工作模式的差异为,初始化时需要引入非线性函数F输出W通过舍弃最低为比特得到u,而工作模式不需要
一般分为两种情况:upload successful

第二层:比特重组(BR)

比特重组在LFSR和F之间,起到数据组合和关联的作用
在LFSR的寄存器单元中抽取128比特进行4个分组4个32比特为X0,X1,X2,X3传递给F
计算过程:
X0=S15H || S14L
X1=S11L || S19H
X2=S7L || S5H
X3=S2L || S0H
其中||表示两个字符首位进行拼接,H代表高16位,L代表低16位

第三层:非线性函数F

非线性函数F内部包含2个32比特存储单元R1和R2,F的输入为来自比特重组的3个32比特字X0,X1,X2,F的输出为一个32比特的W,计算过程:
upload successful
F层核心部件,S盒:非线性部件,为ZUC提供混淆,L变换:线性变换,为ZUC提供扩散,F使用了两个8*8的S盒:
upload successful
upload successful
upload successful
F使用了两个L变换:L1和L2
upload successful
最后结果
upload successful

代码实现:加密

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
#pragma once

#include<malloc.h>
#include<stdio.h>


/* ————————————W—————————- */
typedef unsigned char u8;
typedef unsigned int u32;
/* —————————————t————————- */
/* the state registers of LFSR 16 cells*/
u32 LFSR_S0;
u32 LFSR_S1;
u32 LFSR_S2;
u32 LFSR_S3;
u32 LFSR_S4;
u32 LFSR_S5;
u32 LFSR_S6;
u32 LFSR_S7;
u32 LFSR_S8;
u32 LFSR_S9;
u32 LFSR_S10;
u32 LFSR_S11;
u32 LFSR_S12;
u32 LFSR_S13;
u32 LFSR_S14;
u32 LFSR_S15;
/* the registers of f算法中的R1,R2 */
u32 F_R1;
u32 F_R2;
/* the outputs of BitReorganization BR中的X0,X1,X2,X3*/
u32 BRC_X0;
u32 BRC_X1;
u32 BRC_X2;
u32 BRC_X3;
/* the s-boxes 两个S盒*/
u8 S0[256] = {
0x3e,0x72,0x5b,0x47,0xca,0xe0,0x00,0x33,0x04,0xd1,0x54,0x98,0x09,0xb9,0x6d,0xcb,
0x7b,0x1b,0xf9,0x32,0xaf,0x9d,0x6a,0xa5,0xb8,0x2d,0xfc,0x1d,0x08,0x53,0x03,0x90,
0x4d,0x4e,0x84,0x99,0xe4,0xce,0xd9,0x91,0xdd,0xb6,0x85,0x48,0x8b,0x29,0x6e,0xac,
0xcd,0xc1,0xf8,0x1e,0x73,0x43,0x69,0xc6,0xb5,0xbd,0xfd,0x39,0x63,0x20,0xd4,0x38,
0x76,0x7d,0xb2,0xa7,0xcf,0xed,0x57,0xc5,0xf3,0x2c,0xbb,0x14,0x21,0x06,0x55,0x9b,
0xe3,0xef,0x5e,0x31,0x4f,0x7f,0x5a,0xa4,0x0d,0x82,0x51,0x49,0x5f,0xba,0x58,0x1c,
0x4a,0x16,0xd5,0x17,0xa8,0x92,0x24,0x1f,0x8c,0xff,0xd8,0xae,0x2e,0x01,0xd3,0xad,
0x3b,0x4b,0xda,0x46,0xeb,0xc9,0xde,0x9a,0x8f,0x87,0xd7,0x3a,0x80,0x6f,0x2f,0xc8,
0xb1,0xb4,0x37,0xf7,0x0a,0x22,0x13,0x28,0x7c,0xcc,0x3c,0x89,0xc7,0xc3,0x96,0x56,
0x07,0xbf,0x7e,0xf0,0x0b,0x2b,0x97,0x52,0x35,0x41,0x79,0x61,0xa6,0x4c,0x10,0xfe,
0xbc,0x26,0x95,0x88,0x8a,0xb0,0xa3,0xfb,0xc0,0x18,0x94,0xf2,0xe1,0xe5,0xe9,0x5d,
0xd0,0xdc,0x11,0x66,0x64,0x5c,0xec,0x59,0x42,0x75,0x12,0xf5,0x74,0x9c,0xaa,0x23,
0x0e,0x86,0xab,0xbe,0x2a,0x02,0xe7,0x67,0xe6,0x44,0xa2,0x6c,0xc2,0x93,0x9f,0xf1,
0xf6,0xfa,0x36,0xd2,0x50,0x68,0x9e,0x62,0x71,0x15,0x3d,0xd6,0x40,0xc4,0xe2,0x0f,
0x8e,0x83,0x77,0x6b,0x25,0x05,0x3f,0x0c,0x30,0xea,0x70,0xb7,0xa1,0xe8,0xa9,0x65,
0x8d,0x27,0x1a,0xdb,0x81,0xb3,0xa0,0xf4,0x45,0x7a,0x19,0xdf,0xee,0x78,0x34,0x60
};
//s0盒
u8 S1[256] = {
0x55,0xc2,0x63,0x71,0x3b,0xc8,0x47,0x86,0x9f,0x3c,0xda,0x5b,0x29,0xaa,0xfd,0x77,
0x8c,0xc5,0x94,0x0c,0xa6,0x1a,0x13,0x00,0xe3,0xa8,0x16,0x72,0x40,0xf9,0xf8,0x42,
0x44,0x26,0x68,0x96,0x81,0xd9,0x45,0x3e,0x10,0x76,0xc6,0xa7,0x8b,0x39,0x43,0xe1,
0x3a,0xb5,0x56,0x2a,0xc0,0x6d,0xb3,0x05,0x22,0x66,0xbf,0xdc,0x0b,0xfa,0x62,0x48,
0xdd,0x20,0x11,0x06,0x36,0xc9,0xc1,0xcf,0xf6,0x27,0x52,0xbb,0x69,0xf5,0xd4,0x87,
0x7f,0x84,0x4c,0xd2,0x9c,0x57,0xa4,0xbc,0x4f,0x9a,0xdf,0xfe,0xd6,0x8d,0x7a,0xeb,
0x2b,0x53,0xd8,0x5c,0xa1,0x14,0x17,0xfb,0x23,0xd5,0x7d,0x30,0x67,0x73,0x08,0x09,
0xee,0xb7,0x70,0x3f,0x61,0xb2,0x19,0x8e,0x4e,0xe5,0x4b,0x93,0x8f,0x5d,0xdb,0xa9,
0xad,0xf1,0xae,0x2e,0xcb,0x0d,0xfc,0xf4,0x2d,0x46,0x6e,0x1d,0x97,0xe8,0xd1,0xe9,
0x4d,0x37,0xa5,0x75,0x5e,0x83,0x9e,0xab,0x82,0x9d,0xb9,0x1c,0xe0,0xcd,0x49,0x89,
0x01,0xb6,0xbd,0x58,0x24,0xa2,0x5f,0x38,0x78,0x99,0x15,0x90,0x50,0xb8,0x95,0xe4,
0xd0,0x91,0xc7,0xce,0xed,0x0f,0xb4,0x6f,0xa0,0xcc,0xf0,0x02,0x4a,0x79,0xc3,0xde,
0xa3,0xef,0xea,0x51,0xe6,0x6b,0x18,0xec,0x1b,0x2c,0x80,0xf7,0x74,0xe7,0xff,0x21,
0x5a,0x6a,0x54,0x1e,0x41,0x31,0x92,0x35,0xc4,0x33,0x07,0x0a,0xba,0x7e,0x0e,0x34,
0x88,0xb1,0x98,0x7c,0xf3,0x3d,0x60,0x6c,0x7b,0xca,0xd3,0x1f,0x32,0x65,0x04,0x28,
0x64,0xbe,0x85,0x9b,0x2f,0x59,0x8a,0xd7,0xb0,0x25,0xac,0xaf,0x12,0x03,0xe2,0xf2
};
//s1盒
/* the constants D */
u32 EK_d[16] = {
0x44D7, 0x26BC, 0x626B, 0x135E, 0x5789, 0x35E2, 0x7135, 0x09AF,
0x4D78, 0x2F13, 0x6BC4, 0x1AF1, 0x5E26, 0x3C4D, 0x789A, 0x47AC
};
/* ——————————————————————- */
/* c = a + b mod (2^31 – 1) 那个附录里复杂的计算*/
u32 AddM(u32 a, u32 b) {
u32 c = a + b;
return (c & 0x7FFFFFFF) + (c >> 31);
}
/* LFSR with initialization mode */
#define MulByPow2(x, k) ((((x) << k) | ((x) >> (31 - k))) & 0x7FFFFFFF)
void LFSRWithInitialisationMode(u32 u) {
u32 f, v; f = LFSR_S0;
v = MulByPow2(LFSR_S0, 8);
f = AddM(f, v);

v = MulByPow2(LFSR_S4, 20);
f = AddM(f, v);

v = MulByPow2(LFSR_S10, 21);
f = AddM(f, v);

v = MulByPow2(LFSR_S13, 17);
f = AddM(f, v);

v = MulByPow2(LFSR_S15, 15);
f = AddM(f, v);

f = AddM(f, u);
/* update the state */
LFSR_S0 = LFSR_S1;
LFSR_S1 = LFSR_S2;
LFSR_S2 = LFSR_S3;
LFSR_S3 = LFSR_S4;
LFSR_S4 = LFSR_S5;
LFSR_S5 = LFSR_S6;
LFSR_S6 = LFSR_S7;
LFSR_S7 = LFSR_S8;
LFSR_S8 = LFSR_S9;
LFSR_S9 = LFSR_S10;
LFSR_S10 = LFSR_S11;
LFSR_S11 = LFSR_S12;
LFSR_S12 = LFSR_S13;
LFSR_S13 = LFSR_S14;
LFSR_S14 = LFSR_S15;
LFSR_S15 = f;
}
/* LFSR with work mode 工作模式*/
void LFSRWithWorkMode() {
u32 f, v; f = LFSR_S0;
v = MulByPow2(LFSR_S0, 8);
f = AddM(f, v);

v = MulByPow2(LFSR_S4, 20);
f = AddM(f, v);

v = MulByPow2(LFSR_S10, 21);
f = AddM(f, v);

v = MulByPow2(LFSR_S13, 17);
f = AddM(f, v);

v = MulByPow2(LFSR_S15, 15);
f = AddM(f, v);

/* update the state */
LFSR_S0 = LFSR_S1;
LFSR_S1 = LFSR_S2;
LFSR_S2 = LFSR_S3;
LFSR_S3 = LFSR_S4;
LFSR_S4 = LFSR_S5;
LFSR_S5 = LFSR_S6;
LFSR_S6 = LFSR_S7;
LFSR_S7 = LFSR_S8;
LFSR_S8 = LFSR_S9;
LFSR_S9 = LFSR_S10;
LFSR_S10 = LFSR_S11;
LFSR_S11 = LFSR_S12;
LFSR_S12 = LFSR_S13;
LFSR_S13 = LFSR_S14;
LFSR_S14 = LFSR_S15;
LFSR_S15 = f;
}

/* BitReorganization */
void BitReorganization() {
BRC_X0 = ((LFSR_S15 & 0x7FFF8000) << 1) | (LFSR_S14 & 0xFFFF);
BRC_X1 = ((LFSR_S11 & 0xFFFF) << 16) | (LFSR_S9 >> 15);
BRC_X2 = ((LFSR_S7 & 0xFFFF) << 16) | (LFSR_S5 >> 15);
BRC_X3 = ((LFSR_S2 & 0xFFFF) << 16) | (LFSR_S0 >> 15);
}
#define ROT(a, k) (((a) << k) | ((a) >> (32 - k)))
/* L1 */
u32 L1(u32 X) {
return (X ^ ROT(X, 2) ^ ROT(X, 10) ^ ROT(X, 18) ^ ROT(X, 24));
}
/* L2 */
u32 L2(u32 X) {
return (X ^ ROT(X, 8) ^ ROT(X, 14) ^ ROT(X, 22) ^ ROT(X, 30));
}
#define MAKEU32(a, b, c, d) (((u32)(a) << 24) | ((u32)(b) << 16) | ((u32)(c) << 8) | ((u32)(d)))
/* F */
u32 F() {
u32 W, W1, W2, u, v;
W = (BRC_X0 ^ F_R1) + F_R2;
W1 = F_R1 + BRC_X1;
W2 = F_R2 ^ BRC_X2;
u = L1((W1 << 16) | (W2 >> 16));
v = L2((W2 << 16) | (W1 >> 16));
F_R1 = MAKEU32(S0[u >> 24], S1[(u >> 16) & 0xFF],
S0[(u >> 8) & 0xFF], S1[u & 0xFF]);
F_R2 = MAKEU32(S0[v >> 24], S1[(v >> 16) & 0xFF],
S0[(v >> 8) & 0xFF], S1[v & 0xFF]);
return W;
}
#define MAKEU31(a, b, c)(((u32)(a) << 23)|((u32)(b) << 8)|(u32)(c))
/* initialize */
//初始化
void Initialization(u8* k, u8* iv) {
u32 w, nCount;

/* expand key */
LFSR_S0 = MAKEU31(k[0], EK_d[0], iv[0]);
LFSR_S1 = MAKEU31(k[1], EK_d[1], iv[1]);
LFSR_S2 = MAKEU31(k[2], EK_d[2], iv[2]);
LFSR_S3 = MAKEU31(k[3], EK_d[3], iv[3]);
LFSR_S4 = MAKEU31(k[4], EK_d[4], iv[4]);
LFSR_S5 = MAKEU31(k[5], EK_d[5], iv[5]);
LFSR_S6 = MAKEU31(k[6], EK_d[6], iv[6]);
LFSR_S7 = MAKEU31(k[7], EK_d[7], iv[7]);
LFSR_S8 = MAKEU31(k[8], EK_d[8], iv[8]);
LFSR_S9 = MAKEU31(k[9], EK_d[9], iv[9]);
LFSR_S10 = MAKEU31(k[10], EK_d[10], iv[10]);
LFSR_S11 = MAKEU31(k[11], EK_d[11], iv[11]);
LFSR_S12 = MAKEU31(k[12], EK_d[12], iv[12]);
LFSR_S13 = MAKEU31(k[13], EK_d[13], iv[13]);
LFSR_S14 = MAKEU31(k[14], EK_d[14], iv[14]);
LFSR_S15 = MAKEU31(k[15], EK_d[15], iv[15]);
/* set F_R1 and F_R2 to zero */
F_R1 = 0;
F_R2 = 0;
nCount = 32;
while (nCount > 0)
{
BitReorganization();
w = F();
LFSRWithInitialisationMode(w >> 1);
nCount--;
}
}
//生成密钥流
void GenerateKeystream(u32* pKeystream, int KeystreamLen) {
int i;
{
BitReorganization();
F(); /* discard the output of F */
LFSRWithWorkMode();
}
for (i = 0; i < KeystreamLen; i++) {
BitReorganization();
pKeystream[i] = F() ^ BRC_X3;
LFSRWithWorkMode();
}
}
/*Test1 :测试密钥的生成 :
input:
Key: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
IV: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
output: z1: 27bede74
z2: 018082da
*/


int main() {
int i;
u32 z[10];
u8 k1[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
u8 iv1[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
Initialization(k1, iv1);
GenerateKeystream(z, 2);
for (i = 0; i < 2; i++) {
printf("Z[%d],%08X\n",i, z[i]);
}
}

代码实现:解密

upload successful
流密码进行,一般会给出k,iv以及一个密文序列,那么进行异或就可以出来明文

Author: L0x1c
Link: https://l0x1c.github.io/2020/01/03/2020-1-03/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
Donate
  • 微信
    微信
  • 支付寶
    支付寶