维吉尼亚密码 Fay·D·Flourite

维吉尼亚密码


和rsa一样,是补完之前的学习- - ##维吉尼亚密码介绍 维吉尼亚密码的基础是凯撒密码,也是一种移位密码,不过维吉尼亚密码 要复杂的多。 维吉尼亚密码包括了明文,密文和密钥。维吉尼亚密码的加密和密钥密切相关。 它按照密钥每个字母对应的数字来进行字母的移位,这时我们就不能通过简单的移位得到明文了。 如密钥为THE,则按照每第一个字母移20位,第二个字母移8位,第三个字母移5位,第四个字母再移20位…如此循环,完成加密。

##维吉尼亚密码破解 破解维吉尼亚密码,密钥就成了关键。

在未知的情况下,我们先推测密钥的长度,推测的方法是按照相同单词出现的间隔字母数来推测。如密钥为THE,而文中常用单词如YOU,或许会出现不下一次,而当出现两次密钥THE将YOU翻译为同一密文时,就说明用THE轮回了n遍,中间间隔的字母数也就是密钥长度的n倍。这也展示出维吉尼亚密码安全性的来源:足够长的密钥。

推测出长度后,按照推测的长度将密文分为等数的组。如密钥THE,长度为3,则将第1,4,7…个字母分成一组,2,5,8…个字母分成一组,3,6,9….个字母分为一组,共三组。这样一来,就保证了每一组的移位数是一致的。

接下来,用频率攻击方法,分析每一组中字母出现的频率,对照英文的标准字母出现频率表推测移位数,并根据移位数最终推出原文,进行语义分析。这也是个尝试的过程,尤其是当密文长度较短,亦或是密钥长度很长时,在推测密钥长度,推测每一组的移位数上,都有很大的阻碍。

一样贴出二面时写的破解脚本:

from pandas.core.frame import DataFrame
import numpy as np
import pandas as pd
pd.set_option('display.max_rows', None)
pd.set_option('display.max_columns', None)
w=['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']
n=[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]
miwen=input('请输入密文:')
listmiwen=list(miwen)
a1=[]
a2=[]
a3=[]
a4=[]

for i in range(1,int((len(miwen)/4)+1)):        #取出不同位移的字母
    i = 4*i-4
    a1.append(listmiwen[i])

for i in range(1,int((len(miwen)/4)+1)):
    i = 4*i-3
    a2.append(listmiwen[i])

for i in range(1,int((len(miwen)/4)+1)):
    i = 4*i-2
    a3.append(listmiwen[i])

for i in range(1,int((len(miwen)/4)+1)):
    i = 4*i-1
    a4.append(listmiwen[i])
print(len(miwen))
print('---------------------------------------------------------------------------------------------------------------')
print('a出现了',a1.count('a'),'次')               #计数出现次数
print('b出现了',a1.count('b'),'次')
print('c出现了',a1.count('c'),'次')
print('d出现了',a1.count('d'),'次')
print('e出现了',a1.count('e'),'次')
print('f出现了',a1.count('f'),'次')
print('g出现了',a1.count('g'),'次')
print('h出现了',a1.count('h'),'次')
print('i出现了',a1.count('i'),'次')
print('j出现了',a1.count('j'),'次')
print('k出现了',a1.count('k'),'次')
print('l出现了',a1.count('l'),'次')
print('m出现了',a1.count('m'),'次')
print('n出现了',a1.count('n'),'次')
print('o出现了',a1.count('o'),'次')
print('p出现了',a1.count('p'),'次')
print('q出现了',a1.count('q'),'次')
print('r出现了',a1.count('r'),'次')
print('s出现了',a1.count('s'),'次')
print('t出现了',a1.count('t'),'次')
print('u出现了',a1.count('u'),'次')
print('v出现了',a1.count('v'),'次')
print('w出现了',a1.count('w'),'次')
print('x出现了',a1.count('x'),'次')
print('y出现了',a1.count('y'),'次')
print('z出现了',a1.count('z'),'次')
print('---------------------------------------------------------------------------------------------------------------')
print('a出现了',a2.count('a'),'次')               #计数出现次数
print('b出现了',a2.count('b'),'次')
print('c出现了',a2.count('c'),'次')
print('d出现了',a2.count('d'),'次')
print('e出现了',a2.count('e'),'次')
print('f出现了',a2.count('f'),'次')
print('g出现了',a2.count('g'),'次')
print('h出现了',a2.count('h'),'次')
print('i出现了',a2.count('i'),'次')
print('j出现了',a2.count('j'),'次')
print('k出现了',a2.count('k'),'次')
print('l出现了',a2.count('l'),'次')
print('m出现了',a2.count('m'),'次')
print('n出现了',a2.count('n'),'次')
print('o出现了',a2.count('o'),'次')
print('p出现了',a2.count('p'),'次')
print('q出现了',a2.count('q'),'次')
print('r出现了',a2.count('r'),'次')
print('s出现了',a2.count('s'),'次')
print('t出现了',a2.count('t'),'次')
print('u出现了',a2.count('u'),'次')
print('v出现了',a2.count('v'),'次')
print('w出现了',a2.count('w'),'次')
print('x出现了',a2.count('x'),'次')
print('y出现了',a2.count('y'),'次')
print('z出现了',a2.count('z'),'次')
print('---------------------------------------------------------------------------------------------------------------')
print('a出现了',a3.count('a'),'次')               #计数出现次数
print('b出现了',a3.count('b'),'次')
print('c出现了',a3.count('c'),'次')
print('d出现了',a3.count('d'),'次')
print('e出现了',a3.count('e'),'次')
print('f出现了',a3.count('f'),'次')
print('g出现了',a3.count('g'),'次')
print('h出现了',a3.count('h'),'次')
print('i出现了',a3.count('i'),'次')
print('j出现了',a3.count('j'),'次')
print('k出现了',a3.count('k'),'次')
print('l出现了',a3.count('l'),'次')
print('m出现了',a3.count('m'),'次')
print('n出现了',a3.count('n'),'次')
print('o出现了',a3.count('o'),'次')
print('p出现了',a3.count('p'),'次')
print('q出现了',a3.count('q'),'次')
print('r出现了',a3.count('r'),'次')
print('s出现了',a3.count('s'),'次')
print('t出现了',a3.count('t'),'次')
print('u出现了',a3.count('u'),'次')
print('v出现了',a3.count('v'),'次')
print('w出现了',a3.count('w'),'次')
print('x出现了',a3.count('x'),'次')
print('y出现了',a3.count('y'),'次')
print('z出现了',a3.count('z'),'次')
print('---------------------------------------------------------------------------------------------------------------')
print('a出现了',a4.count('a'),'次')               #计数出现次数
print('b出现了',a4.count('b'),'次')
print('c出现了',a4.count('c'),'次')
print('d出现了',a4.count('d'),'次')
print('e出现了',a4.count('e'),'次')
print('f出现了',a4.count('f'),'次')
print('g出现了',a4.count('g'),'次')
print('h出现了',a4.count('h'),'次')
print('i出现了',a4.count('i'),'次')
print('j出现了',a4.count('j'),'次')
print('k出现了',a4.count('k'),'次')
print('l出现了',a4.count('l'),'次')
print('m出现了',a4.count('m'),'次')
print('n出现了',a4.count('n'),'次')
print('o出现了',a4.count('o'),'次')
print('p出现了',a4.count('p'),'次')
print('q出现了',a4.count('q'),'次')
print('r出现了',a4.count('r'),'次')
print('s出现了',a4.count('s'),'次')
print('t出现了',a4.count('t'),'次')
print('u出现了',a4.count('u'),'次')
print('v出现了',a4.count('v'),'次')
print('w出现了',a4.count('w'),'次')
print('x出现了',a4.count('x'),'次')
print('y出现了',a4.count('y'),'次')
print('z出现了',a4.count('z'),'次')


k1=[]
l1=[]
for i in a1:
    k1.append(w.index(i)+1)
for i in k1:
    l1.append(w[i+int(7)-27])

k2=[]
l2=[]
for i in a2:
    k2.append(w.index(i)+1)
for i in k2:
    l2.append(w[i+int(22)-27])

k3=[]
l3=[]
for i in a3:
    k3.append(w.index(i)+1)
for i in k3:
    l3.append(w[i+int(15)-27])

k4=[]
l4=[]
for i in a4:
    k4.append(w.index(i)+1)
for i in k4:
    l4.append(w[i+int(15)-27])

t={
    "1":l1,
    "2":l2,
    "3":l3,
    "4":l4
}
d=DataFrame(t)
print(d)

维吉尼亚密码存在很多需要推测的地方,最后也需要人为判断是否符合语义。所以个人认为全自动破译脚本难度较大。另外二面题给出了密钥长度,所以也没有推测长度的步骤。移位数也是人工推测的- -。脚本有很多不足,待后期完善。