hill密码的Python实现,不实用numpy
时间: 2023-06-24 20:07:05 浏览: 106
Hill密码是一种基于线性代数的密码,它将明文分成n个字母一组,每组n个字母视为一个n维向量,再用一个n x n的矩阵A对明文向量进行乘法变换,得到密文向量,最后将密文向量转化为密文。解密时,对密文向量进行逆变换即可得到明文向量。
下面是一个简单的Python实现,不使用numpy库:
```python
import string
# 明文和密钥只包含大写字母
alphabet = string.ascii_uppercase
def char_to_num(char):
"""将字符转换为数字"""
return alphabet.index(char)
def num_to_char(num):
"""将数字转换为字符"""
return alphabet[num]
def gcd(a, b):
"""计算a和b的最大公约数"""
while b:
a, b = b, a % b
return a
def mod_inverse(a, m):
"""计算a在模m下的逆元"""
for x in range(1, m):
if (a * x) % m == 1:
return x
raise ValueError(str(a) + "没有模" + str(m) + "下的逆元")
def matrix_multiply(matrix, vector):
"""矩阵和向量的乘法"""
result = [0] * len(matrix)
for i in range(len(matrix)):
for j in range(len(vector)):
result[i] += matrix[i][j] * vector[j]
result[i] %= 26
return result
def encrypt(plaintext, key):
"""加密"""
n = len(key)
# 将明文分成n个一组
plaintext = plaintext.upper().replace(" ", "")
plaintext += "X" * ((n - len(plaintext) % n) % n)
groups = [plaintext[i:i + n] for i in range(0, len(plaintext), n)]
# 将密钥转换为矩阵
key_matrix = []
for char in key.upper():
key_matrix.append([char_to_num(char)])
# 计算矩阵的行列式和模26下的逆元
determinant = key_matrix[0][0] * key_matrix[1][1] - key_matrix[0][1] * key_matrix[1][0]
determinant %= 26
inverse = mod_inverse(determinant, 26)
# 计算伴随矩阵
adjugate = [[key_matrix[1][1], -key_matrix[0][1]], [-key_matrix[1][0], key_matrix[0][0]]]
for i in range(2):
for j in range(2):
adjugate[i][j] *= (-1) ** (i + j)
# 计算逆矩阵
inverse_matrix = []
for i in range(2):
inverse_matrix.append([(inverse * adjugate[i][j]) % 26 for j in range(2)])
# 加密每组明文
ciphertext = ""
for group in groups:
# 将明文向量转换为数字列表
vector = [char_to_num(char) for char in group]
# 将明文向量补齐为n维向量
while len(vector) < n:
vector.append(0)
# 将明文向量和密钥矩阵相乘
result = matrix_multiply(inverse_matrix, vector)
# 将数字列表转换为密文字符串
for num in result:
ciphertext += num_to_char(num)
return ciphertext
def decrypt(ciphertext, key):
"""解密"""
n = len(key)
# 将密文分成n个一组
ciphertext = ciphertext.upper().replace(" ", "")
groups = [ciphertext[i:i + n] for i in range(0, len(ciphertext), n)]
# 将密钥转换为矩阵
key_matrix = []
for char in key.upper():
key_matrix.append([char_to_num(char)])
# 计算矩阵的行列式和模26下的逆元
determinant = key_matrix[0][0] * key_matrix[1][1] - key_matrix[0][1] * key_matrix[1][0]
determinant %= 26
inverse = mod_inverse(determinant, 26)
# 计算伴随矩阵
adjugate = [[key_matrix[1][1], -key_matrix[0][1]], [-key_matrix[1][0], key_matrix[0][0]]]
for i in range(2):
for j in range(2):
adjugate[i][j] *= (-1) ** (i + j)
# 计算逆矩阵
inverse_matrix = []
for i in range(2):
inverse_matrix.append([(inverse * adjugate[i][j]) % 26 for j in range(2)])
# 解密每组密文
plaintext = ""
for group in groups:
# 将密文向量转换为数字列表
vector = [char_to_num(char) for char in group]
# 将密文向量和逆矩阵相乘
result = matrix_multiply(inverse_matrix, vector)
# 将数字列表转换为明文字符串
for num in result:
plaintext += num_to_char(num)
return plaintext
```
使用示例:
```python
plaintext = "HELLO WORLD"
key = "GYBNQKURP"
ciphertext = encrypt(plaintext, key)
print(ciphertext) # 输出:UZGKSGZEGO
plaintext = decrypt(ciphertext, key)
print(plaintext) # 输出:HELXOWORLD
```
阅读全文