密码学课程设计-古典密码-维吉尼亚

1 概述

1858年,法国密码学家维吉尼亚提出一种以一系列代换表依次对明文消息的字母序列进行代换的加密方法,即明文消息中出现的同一个字母,在加密时不是完全被同一固定的字母代换,而是根据其出现的位置次序用不同的字母代换。

2 算法原理与设计思路

2.1 首先使用维吉尼亚方阵,它的基本方阵是26列26行。方阵的第一行是a到z按正常顺序排列的字母表,第二行是第一行左移循环一位得到的,其他各行依次类推,方阵如下图所示。

维吉尼亚方阵

2.2 加密时,按照密钥字的指示,决定采用哪一个单表。例如密钥字是iscbupt,加密时,明文的第一个字母用与附加列上字母i相对应的密码表进行加密,明文的第二个字母用与附加列的字母s相对应的密码表进行加密,依次类推。

2.3 令英文字母a,b,„,z对应于从0到25的整数。

加解密方法

3 关键算法分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 加密函数
def Encrypt(plaintext, key_list):
ciphertext = ""
i = 0
for ch in plaintext: # 遍历明文
if i % len(key_list) == 0:
i = 0
if ch.isalpha(): # 明文是否为字母,如果是,则判断大小写,分别进行加密
if ch.isupper():
ciphertext += Alphabet[(ord(ch) - 65 + key_list[i]) % 26]
i += 1
else:
ciphertext += Alphabet[(ord(ch) - 97 + key_list[i]) % 26].lower()
i += 1
else: # 如果密文不为字母,直接添加到密文字符串里
ciphertext += ch
return ciphertext

加密算法的关键是给出初始密钥,例如第一个密钥字母是i,对第一个明文字母c进行加密时,选用左边附加列上的字母i对应的那一行作为代替密码表,查处于c相对应的密文字母是K,依次类推即可得出明文。上述代码中的生成密钥部分为核心代码,只有密钥更长,才能保证密码算法的可靠性。解密算法和加密算法只需要减去密钥继续模26即可得到。

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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#Vigenere密码
Alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'

# 根据输入的key生成key列表
def Get_KeyList(key):
key_list = []
for ch in key:
key_list.append(ord(ch.upper()) - 65)
return key_list

# 加密函数
def Encrypt(plaintext, key_list):
ciphertext = ""
i = 0
for ch in plaintext: # 遍历明文
if i % len(key_list) == 0:
i = 0
if ch.isalpha(): # 明文是否为字母,如果是,则判断大小写,分别进行加密
if ch.isupper():
ciphertext += Alphabet[(ord(ch) - 65 + key_list[i]) % 26]
i += 1
else:
ciphertext += Alphabet[(ord(ch) - 97 + key_list[i]) % 26].lower()
i += 1
else: # 如果密文不为字母,直接添加到密文字符串里
ciphertext += ch
return ciphertext

# 解密函数
def Decrypt(ciphertext, key_list):
plaintext = ""
i = 0
for ch in ciphertext: # 遍历密文
if i % len(key_list) == 0:
i = 0
if ch.isalpha(): # 密文为否为字母,如果是,则判断大小写,分别进行解密
if ch.isupper():
plaintext += Alphabet[(ord(ch) - 65 - key_list[i]) % 26]
i += 1
else:
plaintext += Alphabet[(ord(ch) - 97 - key_list[i]) % 26].lower()
i += 1
else: # 如果密文不为字母,直接添加到明文字符串里
plaintext += ch
return plaintext

def main():
print("加密请按D,解密请按E:")
user_input = input()
while(user_input != 'D' and user_input != 'E'): # 输入合法性判断
print("输入有误!请重新输入:")
user_input = input()
print("请输入密钥:")
key = input()
while (key.isalpha() == False): # 输入合法性判断
print("输入有误!密钥为字母,请重新输入:")
key = input()
key_list = Get_KeyList(key)

# 加密
if user_input == 'D':
print("请输入明文:")
plaintext = input()
ciphertext = Encrypt(plaintext, key_list)
print("密文:")
print(ciphertext)
# 解密
else:
print("请输入密文:")
ciphertext = input()
plaintext = Decrypt(ciphertext, key_list)
print("明文:")
print(plaintext)

if __name__ == '__main__':
main()

运行效果如下图:

运行效果

5 密码安全性分析

多表代换密码体制的分析方法主要分为以下三步:
第一步:确定秘钥的长度,常用方法有卡西斯基测试法和重合指数法;
第二步:确定秘钥,常用的方法是拟重合指数法;
第三步:根据第二步确定的秘钥恢复出明文,如果有条件允许可以验证结论的正确性。

卡西斯基测试法基本原理:
若用给定长度为k的密钥周期地对明文字母加密,则当明文中有两个相同字母组在明文序列中间隔的字母数为k的倍数时,这两个明文字母组对应的密文字母组必然相同。但反过来,若密文中出现两个相同的字母组,他们所对应的明文字母组未必相同,但相同的可能性很大。如果将密文中相同的字母组找出来,并对其间隔的字母数进行综合研究,找出他们间隔字母数的最大公因子,就有可能提取出有关密钥字长度k的信息。

重合指数法

上面对于维吉尼亚密码的分析只有通过大量的密文才能实现,所以较短的密文几乎是不可破译的。


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达,可以邮件至 xingshuaikun@163.com。

×

喜欢就点赞,疼爱就打赏