Hill加密系统(Python)

前言

​ 最近在学习数据安全时,上机课的任务是完成希尔加密算法。因为最近我写Python比较多,所以就想用Python来实现。一开始什么思绪也没有,毕竟我们大数据专业也没有学过密码学。

​ 就在网上找相关的资料,找了好久才理解希尔加密算法。就花了几天课余时间自己写了一个简单的希尔加密系统。

先来了解一下希尔加密算法

加密的基本流程:希尔密码(Hill)使用每个字母在字母表中的顺序作为其对应的数字,即 A=0,B=1,C=2 等,然后将明文转化为 n 维向量,跟一个 n × n 的矩阵相乘,再将得出的结果模 26。注意用作加密的矩阵(即密匙)在 Zn26Z26n 必须是可逆的,否则就不可能解码。只有矩阵的行列式和 26 互质,才是可逆的。

实现过程

定义一个字母表:

1
2
3
alphabet = {0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', 5: 'f', 6: 'g', 7: 'h', 8: 'i', 9: 'j', 10: 'k', 11: 'l',
12: 'm', 13: 'n', 14: 'o', 15: 'p', 16: 'q', 17: 'r', 18: 's', 19: 't', 20: 'u', 21: 'v', 22: 'w',
23: 'x', 24: 'y', 25: 'z'}

将输入的明文转换为一个N为维向量(这里笔者只实现了加密三位字母的字符串):

1
2
3
4
5
6
7
8
9
def text_to_list(text):     # 明文转数字列表
text_list = []
for i in text:
for key,value in alphabet.items():
if value == i:
text_list.append(key)
# print("明文转换数字完成")
return text_list
# print(text_list)

N维向量与密钥矩阵相乘:

1
2
3
text_list = text_to_list(text)
text_array = numpy.array(text_list) # 列表构建矩阵
ciphertext = text_array @ key_list # 加密相乘

相乘结果矩阵转换为字符串:

1
2
3
4
5
6
7
8
def ciphertext_to_text(cirphertext):        # 数字密文转换为字符串密文
cirphertext = cirphertext % 26
# print(f"取余后的矩阵{cirphertext}")
key_text = ""
for element in cirphertext:
key_text += alphabet[int(element)]
print(f"转换为密文:{key_text}")
return key_text

到这里,已经完成了加密。其中需要强调的是,这里笔者使用的是3*3阶加密矩阵,加密矩阵要满足以下条件:

  1. 可逆性:用作加密的密钥矩阵必须是可逆的,否则无法解码。只有矩阵的行列式与 26 互质,才是可逆的。
  2. 行列式与 26 互质:密钥矩阵的行列式必须与 26 互质,以确保可逆性。
  3. 合适的矩阵大小:密钥矩阵的大小必须适合明文分组的长度。

在笔者的代码中,使用的密钥是一个3*3阶的矩阵:

1
key_list = numpy.array([[2, 1, 1], [3, 2, 1], [2, 1, 2]])    

下面是运行的截图:

运行截图

完整代码:

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
import numpy

# 定义一个转换字母表
alphabet = {0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', 5: 'f', 6: 'g', 7: 'h', 8: 'i', 9: 'j', 10: 'k', 11: 'l',
12: 'm', 13: 'n', 14: 'o', 15: 'p', 16: 'q', 17: 'r', 18: 's', 19: 't', 20: 'u', 21: 'v', 22: 'w',
23: 'x', 24: 'y', 25: 'z'}

key_list = numpy.array([[2, 1, 1], [3, 2, 1], [2, 1, 2]]) # 密钥矩阵


def text_to_list(text): # 明文转数字列表
text_list = []
for i in text:
for key,value in alphabet.items():
if value == i:
text_list.append(key)
# print("明文转换数字完成")
return text_list
# print(text_list)


def ciphertext_to_text(cirphertext): # 数字密文转换为字符串密文
cirphertext = cirphertext % 26
# print(f"取余后的矩阵{cirphertext}")
key_text = ""
for element in cirphertext:
key_text += alphabet[int(element)]
print(f"转换为密文:{key_text}")
return key_text


def decrypt(ciphertext, key): # 解密函数 传入参数分别为:带解密的字符串和加密密钥
# 计算密钥矩阵的逆矩阵
inv_key = numpy.linalg.inv(key)
# 字符串转数字列表
num_list = []
for i in ciphertext:
for key, value in alphabet.items():
if value == i:
num_list.append(key)

# 将密文矩阵与逆矩阵相乘
decrypted = numpy.round(num_list @ inv_key).astype(int)

# 将数字转换回字母
decrypted_text = ""
for element in decrypted:
element = (element + 2600) % 26 # +2600是为了解决和解密矩阵相乘后有负数的情况
decrypted_text += alphabet[int(element)]

print(f"解密结果:{decrypted_text}")

return decrypted_text


if __name__ == "__main__":
while( True ):
print("-------------------------------------Hill加密系统----------------------------------------------")
print("1.加密")
print("2.解密")
print("3.退出")
choose = input("请输入:")
if choose == '1':
text = input("输入待加密的三位小写字母字符串:")
text_list = []
text_list = text_to_list(text)
text_array = numpy.array(text_list) # 列表构建矩阵
ciphertext = text_array @ key_list # 加密相乘
# print(f"相乘后的矩阵:{ciphertext}")
key_text = ciphertext_to_text(ciphertext)
elif choose == '2':
key_text = input("输入待解密的三位小写字母密文:")
decrypt(key_text, key_list) # 解密
elif choose == '3':
print("感谢使用,期待下次使用!")
break
else:
print("---------------------------------------非法输入!----------------------------------------------")

最后,感谢观看!