python实现维吉利亚密码加密(Vigenère cipher)

最近有个朋友问我关于维吉利亚密码如何用python实现加密,研究之后发现这是个挺好玩的东西,遂决定写篇博文记录一下。

一、何谓维吉利亚密码

第一列是密钥字母列,第一行是明文字母行。不难看出维吉利亚密码是基于凯撒加密进一步的延伸,使用了密钥的概念来对抗字频统计。

 

维吉尼亚密码引入了“密钥”的概念,即根据密钥来决定用哪一行的密表来进行替换,以此来对抗字频统计。假如以上面第一行代表明文字母,左面第一列代表密钥字母,对如下明文加密:
TO BE OR NOT TO BE THAT IS THE QUESTION
当选定RELATIONS作为密钥时,加密过程是:明文一个字母为T,第一个密钥字母为R,因此可以找到在R行中代替T的为K,依此类推,得出对应关系如下:
密钥:RELAT IONSR ELATI ONSRE LATIO NSREL
明文:TOBEO RNOTT OBETH ATIST HEQUE STION
密文:KSMEH ZBBLK SMEMP OGAJX SEJCS FLZSY
历史上以维吉尼亚密表为基础又演变出很多种加密方法,其基本元素无非是密表与密钥,并一直沿用到二战以后的初级电子密码机上。
 

二、python实现

整个程序其实没有太大的难度,顺便这也是我的第一个python项目(以前都是c++),有问题的话请不吝指教。
首先我们新建一个pyhton文档命名为“Defines”,之后直接建立之前提到的凯撒表(上图)
CaesaTable = [['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'],
            ['b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'a'],
            ['c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'a', 'b'],
            ['d', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'a', 'b', 'c'],
            ['e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'a', 'b', 'c', 'd'],
            ['f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'a', 'b', 'c', 'd', 'e'],
            ['g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'a', 'b', 'c', 'd', 'e', 'f'],
            ['h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'a', 'b', 'c', 'd', 'e', 'f', 'g'],
            ['i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'],
            ['j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'],
            ['k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'],
            ['l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k'],
            ['m', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l'],
            ['n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm'],
            ['o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n'],
            ['p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o'],
            ['q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'],
            ['r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q'],
            ['s', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r'],
            ['t', 'u', 'v', 'w', 'x', 'y', 'z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's'],
            ['u', 'v', 'w', 'x', 'y', 'z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't'],
            ['v', 'w', 'x', 'y', 'z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u'],
            ['w', 'x', 'y', 'z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v'],
            ['x', 'y', 'z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w'],
            ['y', 'z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x'],
            ['z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y']]

之后为了方便我们将字母转换为对应的index,我们再建立一个alphabet:

alphabet = 'abcdefghijklmnopqrstuvwxyz'

 

 有了如上的定义,我们便可以实现程序的核心部分,新建文档“main.py”。主程序如下,简单易懂:

import Defines

print("Please input your encryption key")
key = raw_input('Key: ')

print("Please input your encryption text")
text = raw_input('Text: ')

pos = 0
ans = ""

for x in text:
    if x == " ":
        ans += " "
        continue
    i = Defines.alphabet.find(x)
    cipherKey = key[pos]
    j = Defines.alphabet.find(cipherKey)
    ans += Defines.CaesaTable[i][j]
    if pos == len(key) - 1:
        pos = 0
    else:
        pos += 1

print "\nAns:", ans

 

前七行非常简单,是基本的输入,得到用户指定的Key和需要加密的Text。之后我们定义了两个稍后会用的变量,pos用于实现key的循环,ans用作最后结果的输出。

在循环内,首先我们判断正在处理的这个字符是不是空格,如果是则输出空格后直接跳过,如果不是进入下一步操作。i代表凯撒表内横行的位置,我们使用find函数直接在先前定义的alphabet中寻找,获得index。因为在维吉利亚加密中,密钥长度有可能小于明文或大于名文,所以我们需要用pos作为循环的索引,之后在key中获得当前字符对应的key。比如说明文是BIG BROTHER IS WATCH YOU,密钥为APPLE,则对应关系如下:

BIG BROTHER IS WATCHING YOU

APP LEAPPLE AP PLEAPPLE APP

接着我们可以用一样的方法获得密钥的index值,然后再先前建立的凯撒表中获得对应的字母,添加到输出中。最后更新索引pos的值。

至此我们的程序就完工啦,有心的读者可以再试着完善程序的健壮性,比如遇到数字时如何加密,遇到大小写混杂时如何处理。

运行效果:

 

参考资料:

https://baike.baidu.com/item/%E7%BB%B4%E5%90%89%E5%B0%BC%E4%BA%9A%E5%AF%86%E7%A0%81/4905472?fr=aladdin

http://www.zhihu.com/question/20864009/answer/42832661

https://blog.csdn.net/anderslu/article/details/53504300

posted on 2018-03-28 12:09  Scobbing  阅读(2861)  评论(0编辑  收藏  举报

导航