对称加密算法

admin 2022年1月6日01:44:56安全博客 CTF专场评论12 views9538字阅读31分47秒阅读模式

对称密码算法有时又叫传统密码算法、秘密密钥算法或单密钥算法。对称密码算法的加密密钥能够从解密密钥中推算出来,反过来也成立。在大多数对称算法中,加密解密密钥是相同的。它要求发送者和接收者在安全通信之前,商定一个密钥。对称算法的安全性依赖于密钥,泄漏密钥就意味着任何人都能对消息进行加密解密。只要通信需要保密,密钥就必须保密。

对称算法又可分为两类。一次只对明文中的单个位(有时对字节)运算的算法称为序列算法或序列密码。另一类算法是对明文的一组位进行运算,这些位组称为分组,相应的算法称为分组算法或分组密码。现代计算机密码算法的典型分组长度为64位――这个长度既考虑到分析破译密码的难度,又考虑到使用的方便性。后来,随着破译能力的发展,分组长度又提高到128位或更长。

对称密码常用的数学运算
对称密码当中有几种常用到的数学运算。这些运算的共同目的就是把被加密的明文数码尽可能深地打乱,从而加大破译的难度。

◆移位和循环移位
  移位就是将一段数码按照规定的位数整体性地左移或右移。循环右移就是当右移时,把数码的最后的位移到数码的最前头,循环左移正相反。例如,对十进制数码12345678循环右移1位(十进制位)的结果为81234567,而循环左移1位的结果则为23456781。
◆置换
  就是将数码中的某一位的值根据置换表的规定,用另一位代替。它不像移位操作那样整齐有序,看上去杂乱无章。这正是加密所需,被经常应用。
◆扩展
  就是将一段数码扩展成比原来位数更长的数码。扩展方法有多种,例如,可以用置换的方法,以扩展置换表来规定扩展后的数码每一位的替代值。
◆压缩
  就是将一段数码压缩成比原来位数更短的数码。压缩方法有多种,例如,也可以用置换的方法,以表来规定压缩后的数码每一位的替代值。
◆异或
  这是一种二进制布尔代数运算。异或的数学符号为⊕ ,它的运算法则如下:

1
2
3
4
1⊕1 = 0
0⊕0 = 0
1⊕0 = 1
0⊕1 = 1

  也可以简单地理解为,参与异或运算的两数位如相等,则结果为0,不等则为1。
◆迭代
  迭代就是多次重复相同的运算,这在密码算法中经常使用,以使得形成的密文更加难以破解。

DES

DES算法为密码体制中的对称密码体制。需要加密的明文按64位进行分组,加密密钥是根据用户输入的秘钥生成的,密钥长64位,但密钥事实上是56位参与DES运算(第8、16、24、32、40、48、56、64位是校验位, 使得每个密钥都有奇数个1,在计算密钥时要忽略这8位),分组后的明文组和56位的密钥按位替代或交换的方法形成密文组的加密方法

DES算法加密流程描述
(1)输入64位明文数据,并进行初始置换IP;
(2)在初始置换IP后,明文数据再被分为左右两部分,每部分32位,以L0,R0表示;
(3)在秘钥的控制下,经过16轮运算(f);
(4)16轮后,左、右两部分交换,并连接再一起,再进行逆置换;
(5)输出64位密文。

对称加密算法
python实现

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
# -- coding: utf-8 ---
import libnum
import binascii
import base64
#IP置换表 表示源数据的位置
IP_table=[58, 50, 42, 34, 26, 18, 10, 2,
60, 52, 44, 36, 28, 20, 12, 4,
62, 54, 46, 38, 30, 22, 14, 6,
64, 56, 48, 40, 32, 24, 16, 8,
57, 49, 41, 33, 25, 17, 9, 1,
59, 51, 43, 35, 27, 19, 11, 3,
61, 53, 45, 37, 29, 21, 13, 5,
63, 55, 47, 39, 31, 23, 15, 7]
#逆IP置换表
IP_table_=[40, 8, 48, 16, 56, 24, 64, 32,
39, 7, 47, 15, 55, 23, 63, 31,
38, 6, 46, 14, 54, 22, 62, 30,
37, 5, 45, 13, 53, 21, 61, 29,
36, 4, 44, 12, 52, 20, 60, 28,
35, 3, 43, 11, 51, 19, 59, 27,
34, 2, 42, 10, 50, 18, 58, 26,
33, 1, 41, 9, 49, 17, 57, 25]
#密钥生成的置换表1 去校验位 64bit->56bit
PC_1=[ 57, 49, 41, 33, 25, 17, 9,
1, 58, 50, 42, 34, 26, 18,
10, 2, 59, 51, 43, 35, 27,
19, 11, 3, 60, 52, 44, 36,
63, 55, 47, 39, 31, 23, 15,
7, 62, 54, 46, 38, 30, 22,
14, 6, 61, 53, 45, 37, 29,
21, 13, 5, 28, 20, 12, 4]
#密钥生成的置换压缩表2 56bit->48bit
PC_2=[14, 17, 11, 24, 1, 5,
3, 28, 15, 6, 21, 10,
23, 19, 12, 4, 26, 8,
16, 7, 27, 20, 13, 2,
41, 52, 31, 37, 47, 55,
30, 40, 51, 45, 33, 48,
44, 49, 39, 56, 34, 53,
46, 42, 50, 36, 29, 32]
#S盒中的S1盒
S1=[14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13]
#S盒中的S2盒
S2=[15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9]
#S盒中的S3盒
S3=[10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12]
#S盒中的S4盒
S4=[7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14]
#S盒中的S5盒
S5=[2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3]
#S盒中的S6盒
S6=[12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13]
#S盒中的S7盒
S7=[4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12]
#S盒中的S8盒
S8=[13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11]
# S盒
S=[S1,S2,S3,S4,S5,S6,S7,S8]
#P盒
P_table=[16, 7, 20, 21,
29, 12, 28, 17,
1, 15, 23, 26,
5, 18, 31, 10,
2, 8, 24, 14,
32, 27, 3, 9,
19, 13, 30, 6,
22, 11, 4, 25]
#用于对数据进行扩展置换 32bit->48bit
E_table=[32, 1, 2, 3, 4, 5,
4, 5, 6, 7, 8, 9,
8, 9, 10, 11, 12, 13,
12, 13, 14, 15, 16, 17,
16, 17, 18, 19, 20, 21,
20, 21, 22, 23, 24, 25,
24, 25, 26, 27, 28, 29,
28, 29, 30, 31, 32,1]

#按位异或函数
def Xor(a,b):
temp=''
for i in range(len(a)):
temp+=chr((ord(a[i])-48)^(ord(b[i])-48)+48)
return temp

#置换表函数
def Change(a,table):
temp_R = ''
for i in table:
temp_R += a[i - 1]
return temp_R

def S_Change(m):
result=''
#print len(m) #48位
for i in range(len(m)/6):
temp_m=m[6*i:6*(i+1)]
line=(ord(temp_m[0])-48)*2+(ord(temp_m[5])-48)
ranks=(ord(temp_m[1])-48)*8+(ord(temp_m[2])-48)*4+(ord(temp_m[3])-48)*2+(ord(temp_m[4])-48)
result+=('{:04b}'.format(S[i][line*16+ranks])) #十进制转换为4位二进制 高位补零
#print result
return result

#生成16组密钥的F函数
def F(R,key):
#扩展置换E
#print R
R = Change(R,E_table)
#print 'R:'+R
#print 'key:'+key
temp_R=Xor(R,key) #和变换后的48bit key异或
#print temp_R
temp_R=S_Change(temp_R) # 八个置换盒 48bit->32bit
#print len(temp_R) #32bit
temp_R=Change(temp_R,P_table)
return temp_R

#PKCS7Padding:
def Padding(m):
if len(m)%8==0:
# m+='\x08'*8 #根据填充方式不同而选择
m=m
else:
#m+=unichr(8-(len(m)%8))*(8-(len(m)%8)) #填充Unicode编码数据
m+='\00'*(8-(len(m)%8))
return m

#16轮加密
def Des_decode(m,k):
#print m
m=Change(m,IP_table) #IP置换
L=m[0:32]
R=m[32:64]
'''
print 'L:' + L, len(L)
print 'R:' + R, len(R)
'''
for i in range(15):
Temp=R
R=Xor(L,F(R,k[i]))
L=Temp
temp_m=Xor(L,F(R,k[15]))+R
return Change(temp_m,IP_table_)

#生成16轮密钥
def Create_key(k):
key = [''] * 16
# 去校验码置换1
k=Change(k,PC_1)
#print 'temp_k1:' + temp_k1, len(temp_k1)
# 16轮密钥生成
for i in range(1,17):
C=k[0:28]
D=k[28:56]
'''
print 'C:'+C,len(C)
print 'D:'+D,len(D)
'''
# 循环左移
if i==1 or i==2 or i==9 or i==16 : # 1,2,9,16轮循环左移1位
C = C[1:] + C[:1]
D = D[1:] + D[:1]
else: # 其余轮数循环左移2位
C = C[2:] + C[:2]
D = D[2:] + D[:2]
k=C+D # 更新k
#print len(k) #56位
# 压缩置换2 生成密钥 56->48
new_k = Change(k, PC_2)
key[i-1]=new_k
'''
print key
for i in key:
print i
'''
return key

#分组/padding/生成16组密钥
def Des(m,k):
cipher = ''
'''
print "after padding:",
print hex(libnum.s2n(m)),len(m)
print "k:"+k
'''
#key=Create_key(k)
#print key
for i in range(len(m)/8):
#print m[8*i:8*(i+1)],libnum.s2b(m[8*i:8*(i+1)]),len(libnum.s2b(m[8*i:8*(i+1)]))
cipher+=Des_decode(libnum.s2b(m[8*i:8*(i+1)]),k)
return cipher

if __name__=='__main__':
'''
while(1):
key = raw_input("Enter key of 8bytes:") #8位key
if len(key)==8:
break
print "error length"
message =raw_input("Enter message of any length:")
'''
key='abcdefgh'
message='a'

message = Padding(message) #padding
key = Create_key(libnum.s2b(key)) #create key 字符串转二进制
print binascii.b2a_hex(message) # 字符串转对应16进制ASCII码

cipher=Des(message,key) #加密
print "cipher二进制:" + cipher
print "cipher十六进制:"+hex(int(cipher, 2))[2:]

key=key[::-1]
if hex(int(cipher, 2))[-1]=='L':
cipher = Des(hex(int(cipher, 2))[2:-1].decode('hex'), key) #解密 要去掉末尾的'L'
else:
cipher = Des(hex(int(cipher, 2))[2:].decode('hex'), key) # 解密
print "message二进制:" + cipher
print "message十六进制:" + hex(int(cipher, 2))[2:]

#print base64.b64encode(hex(int(cipher, 2))[2:].decode('hex') ) #二进制字符串识别成十进制
#print len(cipher)

3DES

由于DES密码长度容易被暴力破解,所以3DES算法通过对DES算法进行改进,增加DES的密钥长度来避免类似的攻击,针对每个数据块进行三次DES加密;因此,3DES加密算法并非什么新的加密算法,是DES的一个更安全的变形,它以DES为基本模块,通过组合分组方法设计出分组加密算法。。

加/解密过程
该算法的加解密过程分别是对明文/密文数据进行三次DES加密或解密,得到相应的密文或明文。

假设EK()和DK()分别表示DES的加密和解密函数,P表示明文,C表示密文,那么加解密的公式如下:
加密:C = EK3( DK2( EK1(P)) ),即对明文数据进行,加密 –> 解密 –> 加密的过程,最后得到密文数据;
解密:P = DK1( EK2( DK3(C)) ),即对密文数据进行,解密 –> 加密 –> 解密的过程,最后得到明文数据;

其中:K1表示3DES中第一个8字节密钥,K2表示第二个8字节密钥,K3表示第三个8字节密钥,K1、K2、K3决定了算法的安全性,若三个密钥互不相同,本质上就相当于用一个长为168位的密钥进行加密。多年来,它在对付强力攻击时是比较安全的。若数据对安全性要求不那么高,K1可以等于K3。在这种情况下,密钥的有效长度为112位,即K1对应KL(左8字节),K2对应KR(右8字节),K3对应KL(左8字节)。

对称加密算法
当三重密钥均相同时,前两步相互抵消,相当于仅实现了一次加密,因此可实现对普通DES加密算法的兼容。

AES

AES为分组密码,分组密码也就是把明文分成一组一组的,每组长度相等,每次加密一组数据,直到加密完整个明文。在AES标准规范中,分组长度只能是128位,也就是说,每个分组为16个字节(每个字节8位)。密钥的长度可以使用128位、192位或256位。密钥的长度不同,推荐加密轮数也不同,如下表所示:

AES 密钥长度(32位比特字) 分组长度(32位比特字) 加密轮数
AES-128 4 4 10
AES-192 6 4 12
AES-256 8 4 14

轮数在下面介绍,这里实现的是AES-128,也就是密钥的长度为128位,加密轮数为10轮。
上面说到,AES的加密公式为C = E(K,P),在加密函数E中,会执行一个轮函数,并且执行10次这个轮函数,这个轮函数的前9次执行的操作是一样的,只有第10次有所不同。也就是说,一个明文分组会被加密10轮。AES的核心就是实现一轮中的所有操作。

AES的处理单位是字节,128位的输入明文分组P和输入密钥K都被分成16个字节,分别记为P = P0 P1 … P15 和 K = K0 K1 … K15。如,明文分组为P = abcdefghijklmnop,其中的字符a对应P0,p对应P15。一般地,明文分组用字节为单位的正方形矩阵描述,称为状态矩阵。在算法的每一轮中,状态矩阵的内容不断发生变化,最后的结果作为密文输出。该矩阵中字节的排列顺序为从上到下、从左至右依次排列,如下图所示:
对称加密算法
现在假设明文分组P为”abcdefghijklmnop”,则对应上面生成的状态矩阵图如下:
对称加密算法
上图中,0x61为字符a的十六进制表示。可以看到,明文经过AES加密后,已经面目全非。

类似地,128位密钥也是用字节为单位的矩阵表示,矩阵的每一列被称为1个32位比特字。通过密钥编排函数该密钥矩阵被扩展成一个44个字组成的序列W[0],W[1], … ,W[43],该序列的前4个元素W[0],W[1],W[2],W[3]是原始密钥,用于加密运算中的初始密钥加(下面介绍);后面40个字分为10组,每组4个字(128比特)分别用于10轮加密运算中的轮密钥加,如下图所示:
对称加密算法
上图中,设K = “abcdefghijklmnop”,则K0 = a, K15 = p, W[0] = K0 K1 K2 K3 = “abcd”。

AES的整体结构如下图所示,其中的W[0,3]是指W[0]、W[1]、W[2]和W[3]串联组成的128位密钥。加密的第1轮到第9轮的轮函数一样,包括4个操作:字节代换、行位移、列混合和轮密钥加。最后一轮迭代不执行列混合。另外,在第一轮迭代之前,先将明文和原始密钥进行一次异或加密操作。
对称加密算法
上图也展示了AES解密过程,解密过程仍为10轮,每一轮的操作是加密操作的逆操作。由于AES的4个轮操作都是可逆的,因此,解密操作的一轮就是顺序执行逆行移位、逆字节代换、轮密钥加和逆列混合。同加密操作类似,最后一轮不执行逆列混合,在第1轮解密之前,要执行1次密钥加操作

分组密码模式

DES 和 AES 都属于分组密码,他们只能加密固定长度的明文。
分组加密会将明文消息划分为固定大小的块,每块明文分别在密钥控制下加密为密文。当然并不是每个消息都是相应块大小的整数倍,所以我们可能需要进行填充。

ECB

ECB 模式全称为电子密码本模式(Electronic codebook),在ECB模式中,将明文分组加密之后的结果将直接成为密文分组。
加密:
对称加密算法
解密:
对称加密算法
攻击方式
直接找几组不同的密文,然后截取再拼接进行重放攻击

CBC

CBC 全称为密码分组链接(Cipher-block chaining) 模式。在CBC模式中,首先将明文分组与前一个密文分组进行XOR运算,然后再进行加密。
加密:
对称加密算法
解密:
对称加密算法
CBC字节翻转攻击
对称加密算法
Padding oracle attack
填充提示攻击是一种利用分组密码中的填充部分来进行攻击的方法,在分组密码中,当明文长度不为分组长度的整数倍时,需要在最后一个分组中填充一些数据使其凑满一个分组长度。

https://www.freebuf.com/articles/web/15504.html

CFB

CFB 全称为密文反馈模式(Cipher feedback)。明文分组和密文分组之间并没有经过加密这一步骤,只有一个XOR。

重放攻击

OFB

FB 全称为输出反馈模式(Output feedback),其反馈内容是分组加密后的内容而不是密文
加密
对称加密算法
解密

CTR

CTR 模式全称是CounTeR模式(计数器模式),CTR模式是一种通过将逐次累积的计数器进行加密来生成密钥流的流密码。
加密
对称加密算法
解密

参考文章
DES加密算法原理:whttps://www.jianshu.com/p/c44a8a1b7c38
DES加密算法分析:http://ronpa.top/2018/08/20/DES%E5%8A%A0%E5%AF%86%E7%AE%97%E6%B3%95%E5%88%86%E6%9E%90/
AES 加密算法的原理详解:https://blog.csdn.net/gulang03/article/details/81175854
ctfwiki:https://ctf-wiki.org/crypto/blockcipher/mode/introduction/

FROM :blog.cfyqy.com | Author:cfyqy

特别标注: 本站(CN-SEC.COM)所有文章仅供技术研究,若将其信息做其他用途,由用户承担全部法律及连带责任,本站不承担任何法律及连带责任,请遵守中华人民共和国安全法.
  • 我的微信
  • 微信扫一扫
  • weinxin
  • 我的微信公众号
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年1月6日01:44:56
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                  对称加密算法 http://cn-sec.com/archives/722560.html

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: