0%

几种古典密码代码实现

最近在备考软考信息安全工程师,学习到密码学部分,为了记忆更加深刻,将已经掌握并且觉得比较有趣的密码算法用Python来实现,简单记录一下。

古典密码接触到置换密码、代替密码和代数密码三种,其中置换密码相对简单,靠眼睛就可以完成加解密,所以没有必要实现了,代替密码主要有加法密码、乘法密码和仿射密码,仿射密码研究的是Vigenre密码,该密码是16世纪法国密码学家Vigenre使用过的密码,代数密码研究的是Vernam密码,该密码是美国电话电报公司的Gillbert Vernam在1917年为电报通信设计的一种非常方便的密码(我最喜欢这组密码)。

加法密码

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
# coding:utf-8
# 加法密码实现
# 当前仅支持大写字符串加解密
# 秋风木叶 2019-3-10

# 字符串转单字符列表,再转为数字序列便于计算
def stoc(str):
ch_list = []
for i in str:
ch_list.append(i)
return [ord(i)-65 for i in ch_list]

# Int to Chr
# 将数字序列还原成大写字母序列
def itoc(list_int):
A = [chr(i+65) for i in list_int]
ch = ""
for i in A:
ch += i
return ch

# 计算密文序列
def Encrypt(Message,k,n):
print('>>>使用加法密码算法进行加密(k={}, n={})'.format(k,n))
return itoc([i+k%n for i in stoc(Message)])

# 计算明文序列
def Decrypt(Ciphertext,k,n):
# 解密方式1:通过构建密码表进行查表解密
# 解密方式2:通过加密逆运算计算明文
DecryptionType = 2
if(DecryptionType == 1):
print('>>>构建密码表:')
A = [i for i in range(0,n)]
print('>>>明文字母表:{}'.format(itoc(A)))
B = Encrypt(itoc(A),k,n)
print('>>>密文字母表:{}'.format(B))
CiphertextTables = dict(zip(B,A))
print('>>>构建密码表进行查表解密')
return itoc([CiphertextTables[i] for i in Ciphertext])
else:
print('>>>通过加密逆运算进行解密(k的逆元为:{})'.format(-k))
return itoc([c-k+n %n for c in stoc(Ciphertext)])

if __name__=='__main__':
# 当前仅支持大写字母串
A = ('ABCDEF')
print('输入的明文字符串为:{}'.format(A))
B = Encrypt(A,7,26)
print('加密后的密文:{}'.format(B))
C = Decrypt(B,7,26)
print('解密后的明文:{}'.format(C))

以上代码的执行结果:

1
2
3
4
5
输入的明文字符串为:ABCDEF
>>>使用加法密码算法进行加密(k=7, n=26)
加密后的密文:HIJKLM
>>>通过加密逆运算进行解密(k的逆元为:-7)
解密后的明文:ABCDEF

加法密码比较简单,加解密过程既可以通过公式计算实现,也可以使用查表的方式获得,代码中解密过程就分别使用了加密逆运算和查表两种思路来实现。

乘法密码

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
# coding:utf-8
# 乘法密码计算实现代码
# 当前仅支持大写字符串加解密,参数k和n必须互质整数
# 秋风木叶 2019-3-9

# 字符串转单字符列表,再转为数字序列便于计算
def stoc(str):
ch_list = []
for i in str:
ch_list.append(i)
return [ord(i)-65 for i in ch_list]

# Int to Chr
# 将数字序列还原成大写字母序列
def itoc(list_int):
A = [chr(i+65) for i in list_int]
ch = ""
for i in A:
ch += i
return ch

# 计算密文序列
def Encrypt(Message,k,n):
print('>>>使用乘法密码算法进行加密(k={}, n={})'.format(k,n))
return itoc([i*k%n for i in stoc(Message)])

# 计算明文序列
def Decrypt(Ciphertext,k,n):
# 解密方式1:通过构建密码表进行查表解密
# 解密方式2:通过加密逆运算计算明文
DecryptionType = 2
if(DecryptionType == 1):
print('>>>构建密码表:')
A = [i for i in range(0,n)]
print('>>>明文字母表:{}'.format(itoc(A)))
B = Encrypt(itoc(A),k,n)
print('>>>密文字母表:{}'.format(B))
CiphertextTables = dict(zip(B,A))
print('>>>构建密码表进行查表解密')
return itoc([CiphertextTables[i] for i in Ciphertext])
else:
for k1 in range(0, n):
if(k1 * k % n == 1):
break
print('>>>通过加密逆运算进行解密(k的逆元为:{})'.format(k1))
return itoc([c*k1%n for c in stoc(Ciphertext)])

if __name__=='__main__':
# 当前仅支持大写字母串
A = ('ABCDEF')
print('输入的明文字符串为:{}'.format(A))
B = Encrypt(A,7,26)
print('加密后的密文:{}'.format(B))
C = Decrypt(B,7,26)
print('解密后的明文:{}'.format(C))

以上代码的执行结果:

1
2
3
4
5
输入的明文字符串为:ABCDEF
>>>使用乘法密码算法进行加密(k=7, n=26)
加密后的密文:AHOVCJ
>>>通过加密逆运算进行解密(k的逆元为:15)
解密后的明文:ABCDEF

乘法密码要求k和n互质,否则不能正确求解,代码整体结构跟加法密码相同,区别在于核心算法更加复杂。

仿射密码之Vigenre密码

仿射密码用到多个密文字母表,也成为多表代替密码。
最著名的多表代替密码要算16世纪法国学者Vigenre使用过的Vigenre密码,我也正是通过Vigenre密码来学习仿射密码的。

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
# coding:utf-8
# Vigenre密码实现代码
# 当前仅支持大写字符串加解密
# 秋风木叶 2019-3-10

# 字符串转单字符列表
def stoc(str):
ch_list = []
for i in str:
i = i.strip()
if(i != ''):
ch_list.append(i)
return [i for i in ch_list]

# 字符列表转换为字符串
def ctoc(list_ch):
ch = ""
for i in list_ch:
ch += i
return ch

# 构建密码字典
def GetM_C():
A = []
B = []
C = []
for i in range(0,26):
A.append(chr(i+65))
B.append([chr(i+65)])
for j in range(1,26):
B[i].append((chr((i+j)%26+65)))
for i in A:
C.append(dict(zip(A,B[ord(i)-65])))
return C

# 计算密文序列
def Encrypt(Message,K):
M_C = GetM_C()
C = ''
for i,k in zip(stoc(Message),stoc(K)):
#print(i,k)
C += M_C[ord(i)-65][k]
print('>>>使用Vigenre密码算法进行加密')
return C

# 通过查密码表计算明文序列
def Decrypt(Ciphertext,K):
M_C = GetM_C()
M = ''
for c,k in zip(stoc(Ciphertext),stoc(K)):
M_Dict = M_C[ord(k)-65]
#print(M_Dict)
for m in M_Dict.keys():
if(M_Dict[m] == c):
M += m
#print(m)
print('>>>使用Vigenre密码算法进行解密')
return M

if __name__=='__main__':
# 当前仅支持大写字母串
M = ('MING CHEN WU DIAN FA DONG FAN GONG')
K = ('XING CHUI PING YE KUO YUE YONG DA JIANG LIU')
print('输入的明文字符串为:{}'.format(M))
print('输入的密钥字符串为:{}'.format(K))
C = Encrypt(M, K)
print('加密后的密文:{}'.format(C))
M1 = Decrypt(C, K)
print('解密后的明文:{}'.format(M1))

以上代码的执行效果:

1
2
3
4
5
6
输入的明文字符串为:MING CHEN WU DIAN FA DONG FAN GONG
输入的密钥字符串为:XING CHUI PING YE KUO YUE YONG DA JIANG LIU
>>>使用Vigenre密码算法进行加密
加密后的密文:JQAMEOYVLCQOYRPURMHKDOAMRNP
>>>使用Vigenre密码算法进行解密
解密后的明文:MINGCHENWUDIANFADONGFANGONG

暂时仅通过构建密码表的方式来实现,加解密都通过查表来进行,密文和明文长度相等,密钥尤为关键,密钥长度必须大于明文,否则多出来的明文无法加密,同样如果密钥长度小于密文长度部分密文也无法解密。

代数密码之Vernam密码

Vernam密码可谓是截至目前我觉得最有意思的密码了,它通过对二进制序列的异或运算来实现加解密,真是太神奇了,花时间用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
# coding:utf-8
# 代数密码(Vernam)实现代码
# 当前仅支持大写字符串加解密
# 秋风木叶 2019-3-11

# 字符转二进制
def CtoB(ch):
OrdCh = ord(ch)
BinarySequence = ''
while(True):
if(OrdCh % 2 == 0):
BinarySequence += '0'
else:
BinarySequence += '1'
OrdCh = OrdCh // 2
if(OrdCh == 1):
break
#print(OrdCh,BinarySequence)
BinarySequence += '1'
# 补齐8位
length = 8 - len(BinarySequence)
while(length):
BinarySequence += '0'
length -= 1
#print('BinarySequence:{}'.format(BinarySequence))
return BinarySequence[::-1]

# 二进制转字符
def BtoC(Bin):
St = ''
OrdCh = 0
length = 8
for i in Bin:
length -= 1
OrdCh += (ord(i)-ord('0'))*(2**length)
#print(length,i,OrdCh)
if(length == 0):
St += chr(OrdCh)
length = 8
OrdCh = 0
return St

# 核心算法:二进制异或运算(加解密通用)
def Execute_Unit(m_c, k):
result_unit = ''
for i,j in zip(m_c, k):
#print(i,j)
if(i == j):
result_unit += '0'
else:
result_unit += '1'
#print('result_unit:{}'.format(result_unit))
return result_unit

# 调用Vernam算法进行加密
def Encrypt(Message,K):
print('>>>调用Vernam算法进行加密')
result = ''
for m,k in zip(Message, K):
result += Execute_Unit(CtoB(m),CtoB(k))
return result

# 调用Vernam算法进行解密
def Decrypt(Ciphertext,K):
print('>>>调用Vernam算法进行解密')
# Bk存放二进制K值序列
BK = ''
for k in K:
BK += CtoB(k)
# BM存放二进制明文序列
BM = Execute_Unit(Ciphertext, BK[:len(Ciphertext)])
print('>>>二进制密钥序列:{}'.format(BK))
print('>>>二进制明文序列:{}'.format(BM))
return BtoC(BM)

if __name__=='__main__':
# 当前仅支持大写字母串
M = ('MING CHEN WU DIAN FA DONG FAN GONG')
K = ('XING CHUI PING YE KUO YUE YONG DA JIANG LIU')
print('输入的明文字符串为:{}'.format(M))
print('输入的密钥字符串为:{}'.format(K))
C = Encrypt(M, K)
print('加密后的密文:{}'.format(C))
M1 = Decrypt(C, K)
print('解密后的明文:{}'.format(M1))

代码的运行效果如下:

1
2
3
4
5
6
7
8
输入的明文字符串为:MING CHEN WU DIAN FA DONG FAN GONG
输入的密钥字符串为:XING CHUI PING YE KUO YUE YONG DA JIANG LIU
>>>调用Vernam算法进行加密
加密后的密文:00010101000000000000000000000000000000000000000000000000000100000000011100000000000001110001110001101110000000110110100100011000000010110000000000001101000101000110111101100100000101100001101100000010000000000001111100001110000000000110011101100111000010110000111101100111
>>>调用Vernam算法进行解密
>>>二进制密钥序列: 01011000010010010100111001000111001000000100001101001000010101010100100100100000010100000100100101001110010001110010000001011001010001010010000001001011010101010100111100100000010110010101010101000101001000000101100101001111010011100100011100100000010001000100000100100000010010100100100101000001010011100100011100100000010011000100100101010101
>>>二进制明文序列: 01001101010010010100111001000111001000000100001101001000010001010100111000100000010101110101010100100000010001000100100101000001010011100010000001000110010000010010000001000100010011110100111001000111001000000100011001000001010011100010000001000111010011110100111001000111
解密后的明文:MING CHEN WU DIAN FA DONG FAN GONG

本文作者原创,转载请注明出处!

秋风木叶
2019.03.12
有您的赞赏,我会更加有动力!