介绍

维吉尼亚密码(又译维热纳尔密码)是使用一系列凯撒密码组成密码字母表的加密算法,属于多表密码的一种简单形式。 它以其简单易用而著称,同时初学者通常难以破解,因而又被称为“可破译的密码” 。

维吉尼亚密码的核心在于明文,密钥和一张密码表:

维吉尼亚密码表

这一表格包括了26行字母表,每一行都由前一行向左偏移一位得到。具体使用哪一行字母表进行编译是基于密钥进行的,在过程中会不断地变换。

举个例子:

若明文为: The weather is fine today, let's go on a picnic!

选择某个关键词,并重复使其长度与明文相同来生成密钥。

比如选择 calcium 作为关键词,则与明文对应的密钥为: calciumcalciumcalciumcalciumcalciumc

将明文与密钥从左到右一一对应。比如明文第一个字母 $T$ ,它对应密钥第一个字母 $c$,就用密码表中第 $c$ 行,第 $T$ 列的字母 $V$ 来加密明文的字母 $T$ ,以此类推,最后的结果为: Vhp ymufjec ka zupe eqluk, nee'u oi ap a akkhue!

至于解密则相反, 例如:根据密钥第一个字母 $c$ 所对应的 $c$ 行字母表,发现密文第一个字母 $V$ 位于 $T$ 列,因而明文第一个字母为 $T$ ,以此类推便可得到明文。

为什么难以破解?

对包括维吉尼亚密码在内的所有多表密码的破译都是以字母频率为基础的,但直接的频率分析却并不适用。例如,如果P是密文中出现次数最多的字母,则P很有可能对应E(前提是明文的语言为英语)。原因在于E是英语中使用频率最高的字母。然而,由于在维吉尼亚密码中,E可以被加密成不同的密文,因而简单的频率分析在这里并没有用。——摘自 维吉尼亚密码_百度百科

自动加密与解密

有没有觉得手动加密解密维吉尼亚密码实在是太繁琐了?

幸运的是,我们有 一颗勇于爆肝的心 计算机帮助我们自动加密与解密。

根据以上密码规则,我们推出两个公式:($C$ 表示密文,$P$ 表示明文,$K$ 表示密钥)

根据这两个公式,我们写出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
# -*- coding: utf-8
# author: rzm
# time: 2019/10/27

def main():
print("欢迎使用维热纳尔密码加密解密工具.\n")
while True:
res1=input("加密(e) , 解密(d) or 退出(q)? ")
if res1=="e": # 加密
ret=""
text1=input("请输入用于加密的明文: ")
text2=input("密钥: ")
i=0
for ch in text1:
if not ch.isalpha(): # 如果不是英文字符,就直接输出
ret+=ch
continue
tmp1=ord(ch.lower())-ord('a') # 明文中字符的序号
tmp2=ord(text2[i].lower())-ord('a') # 密钥中字符的序号
if ord(ch)>=ord('a') and ord(ch)<=ord('z'): # 如果是小写字母
ret+=chr((tmp1+tmp2)%26+ord('a'))
elif ord(ch)>=ord('A') and ord(ch)<=ord('Z'): # 如果是大写字母
ret+=chr((tmp1+tmp2)%26+ord('A'))
# print(str(tmp1)+" "+str(tmp2)+" "+ret[len(ret)-1])
if i<len(text2)-1: # 循环密钥的指针
i+=1
else:
i=0
print("加密文本: "+ret)
if res1=="d": # 解密
ret=""
text1=input("请输入用于解密的密文: ")
text2=input("密钥: ")
i=0
for ch in text1:
if not ch.isalpha():
ret+=ch
continue
tmp1=ord(ch.lower())-ord('a')
tmp2=ord(text2[i].lower())-ord('a')
if ord(ch)>=ord('a') and ord(ch)<=ord('z'):
ret+=chr((tmp1-tmp2)%26+ord('a'))
elif ord(ch)>=ord('A') and ord(ch)<=ord('Z'):
ret+=chr((tmp1-tmp2)%26+ord('A'))
if i<len(text2)-1:
i+=1
else:
i=0
print("解密文本: "+ret)
if res1=="q": # 退出
break

if __name__=="__main__":
main()

对于windows用户,请前往 Vigenere Cipher.zip下载

对于ubuntu用户,请复制源码,用ubuntu自带的python3解释器运行。