1.维吉尼亚密码(Vigenère Cipher)

维吉尼亚密码是一种经典的多表替换密码,通过一串密钥字母来循环控制每一位明文的移位长度,从而有效抵御简单的频率分析攻击。

1.1加密原理

(1)选取一个密钥单词,将其循环扩展至与明文等长。
(2)对每一位明文字母$m_i$和对应密钥字母$k_i$,加密公式为:

$c_i=(m_i+k_i)mod26$

(3)字谜对应数值:A=0,B=1,…,Z=25

(4)最终将计算结果转回字母,得到密文

1.2解密原理

解密是加密的逆过程,使用相同密钥,将移位反向:

$m_i=(c_i-k_i)mod26$

再转回字母即可恢复明文。

1.3特点

  • 相比凯撒密码更安全,同一个明文字母会被加密成不同密文字母。
  • 密钥越长,安全性越高。
  • 可通过卡西斯基试验、重合指数法进行破解。

1.4加解密代码

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
def vigenere(text, key, mode='encrypt'):
"""维吉尼亚密码加解密
mode: 'encrypt' 加密, 'decrypt' 解密
"""
result = []
key_len = len(key)
key = key.upper()

for i, ch in enumerate(text):
if ch.isalpha():
# 确定大小写基准
base = ord('A') if ch.isupper() else ord('a')#确保解密后字母大小写与原明文一致
# 获取密钥移位值
shift = ord(key[i % key_len]) - ord('A')
if mode == 'encrypt':
shifted = (ord(ch) - base + shift) % 26
else: #mode='decrypt'
shifted = (ord(ch) - base - shift) % 26
result.append(chr(base + shifted))
else:
result.append(ch) #非字母不变
return ''.join(result)

# 使用示例
if __name__ == '__main__':
plaintext = input("请输入待加密明文:")
key = "KEY"
ciphertext = vigenere(plaintext, key, 'encrypt')
print(f"密文: {ciphertext}")
decrypted = vigenere(ciphertext, key, 'decrypt')
print(f"解密: {decrypted}")

2.仿射密码(Affine Cipher)

仿射密码是一种线性替换密码,通过一次函数对字母进行加密,结合了乘法与加法操作,是凯撒密码的推广形式。

2.1加密原理

加密公式:

$c=(am+b)mod26$

  • m:明文字母对应数字

  • a,b:密钥,a 必须与 26 互质(gcd(a,26)=1)

  • c:密文字母对应数字

2.2解密原理

解密需要先求 a 在模 26 下的乘法逆元$a^{-1}$,满足:

$a*a^{-1}=1 (mod26)$

解密公式:

$m=a^{-1}*(c-b)mod 26$

计算后转回字母得到明文。

2.3特点

  • 结构简单、计算高效。

  • 密钥空间较小,容易暴力破解。

  • 是现代线性密码思想的古典雏形。

2.4加解密代码

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
import math
class AffineCipher:
def __init__(self, a, b):
if math.gcd(a,26) != 1:
raise ValueError("a必须与26互质")
self.a = a
self.b = b
self.a_inv=pow(a,-1,26)#计算a的逆元

def encrypt(self, text):
result = ""
for ch in text.upper():
if ch.isalpha():
x = ord(ch) - ord('A')
y = (self.a * x + self.b) % 26
result += chr(y + ord('A'))
else:
result += ch
return result

def decrypt(self, text):
result = ""
for ch in text.upper():
if ch.isalpha():
y = ord(ch) - ord('A')
x = (self.a_inv * (y - self.b)) % 26
result += chr(x + ord('A'))
else:
result += ch
return result

# 使用示例
if __name__ == "__main__":
a=int(input("a:"))
b=int(input("b:"))
cipher = AffineCipher(a, b)
# 加密
plain =input("请输入要加密的明文:")
encrypted = cipher.encrypt(plain)
print(f"明文: {plain}")
print(f"密文: {encrypted}")
# 解密
decrypted = cipher.decrypt(encrypted)
print(f"解密: {decrypted}")

3.Hill密码(Hill Cipher)

Hill 密码由 Lester S. Hill 在 1929 年提出,是首个基于矩阵线性变换的古典密码,以分组为单位加密,能够更好地混淆字母频率。

3.1加密原理

(1)将明文按 n 个字母一组 分组,不足补字母(如 X)。

(2)选取一个 n×n 可逆矩阵 K 作为密钥。

(3)每组明文构成列向量 M,加密:

$C=K*M mod26$

(4)结果向量 C 即为对应密文。

3.2解密原理

求密钥矩阵 K 在模 26 下的逆矩阵$K^{-1}$。

使用逆矩阵解密:

$M=K^{-1}*C mod26$

恢复明文向量并转回字母。

3.3特点

  • 首次引入矩阵与线性代数到密码中。

  • 能够同时加密多个字母,打乱单字母频率。

  • 已知明文攻击下较脆弱。

3.4加解密代码

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

# 字母转数字
def c2n(c):
return ord(c) - ord('A')

# 数字转字母
def n2c(n):
return chr(n + ord('A'))

# 加密
def encrypt(text, key):
n = len(key) # 密钥矩阵大小,即矩阵阶数
text = text.upper().replace(' ', '') #将空格删除

# 明文分组中每组元素个数必须等于密钥矩阵列数n,故填充X使明文长度为n的倍数
while len(text) % n != 0:
text += 'X'

result = ""
for i in range(0, len(text), n): #步长为n,开始循环
# 取出n个字母转成数字向量
vec = np.array([[c2n(ch)] for ch in text[i:i + n]])
# 加密:密钥×向量 mod 26
enc = np.dot(key, vec) % 26
# 转回字母
result += ''.join(n2c(int(x)) for x in enc.flatten())#将[[x], [y]]转回成[x, y]

return result

# 解密
def decrypt(text, key):
n = len(key)

# 求逆矩阵(模26)
det = int(round(np.linalg.det(key)))# 行列式
det_inv = pow(det % 26, -1, 26) # 模逆
inv_key = (np.round(np.linalg.inv(key) * det).astype(int) * det_inv) % 26

result = ""
for i in range(0, len(text), n):
vec = np.array([[c2n(ch)] for ch in text[i:i + n]])
dec = np.dot(inv_key, vec) % 26
result += ''.join(n2c(int(x)) for x in dec.flatten())

return result

#示例
key = np.array([[3, 2], [5, 7]]) # 2x2密钥
plain = "HELLO"

print(f"明文: {plain}")
cipher = encrypt(plain, key)
print(f"密文: {cipher}")
decrypted = decrypt(cipher, key)
print(f"解密: {decrypted}")