python实现维吉尼亚秘钥破解

关于维吉尼亚密码,百度百科中有着较为详细的描述:
维吉尼亚密码——百度百科
维吉尼亚密码的原理与凯撒密码类似,其实是凯撒的一种强化和变形,通过使加密相同明文的秘钥不同,来掩盖字符的频率。
举个栗子:
秘钥为"hello",明文为"today when people ......",通过秘钥加密后结果如下:

加密

可以看到相同的明文e,经过不同的字符加密之后变成了不同的密文,掩盖了明文字符e的字符频率。
但也不是找不到字符频率,我们可以发现,将用"h"字符加密的明文取出之后,就变成了普通的凯撒加密,这是可以通过字符频率分析来破解的。
这就为维吉尼亚秘钥的破解带来了思路。

思路与过程

1.破解秘钥长度N。
2.将密文分成N组,逐个破解秘钥。

用到的数学公式:重合指数

重合指数

其中fi为每个字符在英文当中的频率。fi^2则表示连续取出两个相连的字符,它们相同的概率。英文中对26种情况求和的统计结果约为0.065。
Ni/N为密文中某个字符占密文的比例,假设秘钥长度为key_len,如果key_len组密文中的重合指数IC1也都与0.065接近,那么就可以推测key_len是秘钥长度了。

当秘钥长度key_len知道以后,我们将密文分成key_len个组,计算每个分组的IC2。
举个栗子:如果第一个分组都是用b字符进行加密,那么a字符的频率会转移到b字符上,c字符的频率会转移到d字符上......我们也做这种相应的转移,让b字符在密文的频率(N1/L)和a字符在英文的频率f0相乘,当然这只是其中一种猜测。我们将这26种字符可能都列出来,最接近IC的一定是用b字符加密的那一组。

读者如果想知道详细的资料,可以去网上查找关于重合指数的详细内容,这里也给出一个博客。
密码学原理-篇1:重合指数

步骤

1.破解秘钥长度

首先要有需要破解的密文,密文长度要足够,否则无法破解,笔者给大家一个栗子。

cipher ='Asolm dlpy dlsaws aewv oisfe Flh Ncczw Zcuhrtkoamzy, hoij dvhop evlmc sshhd lbk hzyh avfdh altd cyklywgeetcu. Tpzdsi cpojx qzf px zcwnmylhlh qcct emzia jzff filcg hkz, lh alle hpqp, l upvw dvvapo cmj spf syifff my evl tfmzpg xprpe, dss aswo dlsaws alle vlv qlhoic hoz e xpaiic zt alp Csk Gczgz Scroumklhpsy. Xcyi lyr tscp dlsaws rrph vlv, essf xszinle evlc hpfl gspoaio mm alp zfneytnhxtzb, alp xcuij evlc ozbhxpo khw yzh bwpo wu xsp fpkse khc. Ess prntrlre soz e rcshx ypuhxtgs prqwilrnp cu xsp Flh Ncczw Zcuhrtkoamzy, dlsaws kse efbwe th hrj xcyi, essf ecp bvx htzsmyr hv hzyoai esspv xzblc. Ld tvv xp, W dmww bvx ozbhxp xcuij ec alp zfneytnhxtzb, P gszczi ez upzp xcuij ec alp asywzy kos td wu rppr vj spzw, wz evl qzysf azyh ii elylr mj calpcg, tevp gbvp evl tpcgvr rph alp cshp xzblc.'

字符频率大家在网上也都可以搜得到。

'''
'a': 0.0651738, 'b': 0.0124248, 'c': 0.0217339,
'd': 0.0349835, 'e': 0.1041442, 'f': 0.0197881,
'g': 0.0158610, 'h': 0.0492888, 'i': 0.0558094,
'j': 0.0009033, 'k': 0.0050529, 'l': 0.0331490,
'm': 0.0202124, 'n': 0.0564513, 'o': 0.0596302,
'p': 0.0137645, 'q': 0.0008606, 'r': 0.0497563,
's': 0.0515760, 't': 0.0729357, 'u': 0.0225134,
'v': 0.0082903, 'w': 0.0171272, 'x': 0.0013692,
'y': 0.0145984, 'z': 0.0007836, ' ': 0.1918182
'''

接下来就是破解的python代码

#coding=utf-8
#-*- coding:utf-8 –*-
def c_alpha(cipher):   # 去掉非字母后的密文
    cipher_alpha = ''
    for i in range(len(cipher)):
        if (cipher[i].isalpha()):
            cipher_alpha += cipher[i]
    return cipher_alpha

# 计算cipher的重合指数
def count_CI(cipher):
    N = [0.0 for i in range(26)]
    cipher = c_alpha(cipher)
    L = len(cipher)
    if cipher == '':
        return 0
    else:
        for i in range(L):     #计算所有字母的频数,存在数组N当中
            if (cipher[i].islower()):
                 N[ord(cipher[i]) - ord('a')] += 1
            else:
                 N[ord(cipher[i]) - ord('A')] += 1
    CI_1 = 0
    for i in range(26):
        CI_1 += ((N[i] / L) * ((N[i]-1) / (L-1)))
    return CI_1

# 计算秘钥长度为 key_len 的重合指数
def count_key_len_CI(cipher,key_len):        
    un_cip = ['' for i in range(key_len)]    # un_cip 是分组 
    aver_CI = 0.0
    count = 0
    for i in range(len(cipher_alpha)):
        z = i % key_len
        un_cip[z] += cipher_alpha[i]
    for i in range(key_len):
        un_cip[i]= count_CI(un_cip[i])
        aver_CI += un_cip[i]
    aver_CI = aver_CI/len(un_cip)
    return aver_CI

## 找出最可能的前十个秘钥长度
def pre_10(cipher):
    M = [(1,count_CI(cipher))]+[(0,0.0) for i in range(49)]
    for i in range(2,50):
        M[i] = (i,abs(0.065 - count_key_len_CI(cipher,i)))
    M = sorted(M,key = lambda x:x[1])   #按照数组第二个元素排序
    for i in range(1,10):
        print (M[i])

F = [
0.0651738, 0.0124248, 0.0217339,
0.0349835, 0.1041442, 0.0197881,
0.0158610, 0.0492888, 0.0558094,
0.0009033, 0.0050529, 0.0331490,
0.0202124, 0.0564513, 0.0596302,
0.0137645, 0.0008606, 0.0497563,
0.0515760, 0.0729357, 0.0225134,
0.0082903, 0.0171272, 0.0013692,
0.0145984, 0.0007836
]       # 英文字符频率。
cipher = 'Asolm dlpy dlsaws aewv oisfe Flh Ncczw Zcuhrtkoamzy, hoij dvhop evlmc sshhd lbk hzyh avfdh altd cyklywgeetcu. Tpzdsi cpojx qzf px zcwnmylhlh qcct emzia jzff filcg hkz, lh alle hpqp, l upvw dvvapo cmj spf syifff my evl tfmzpg xprpe, dss aswo dlsaws alle vlv qlhoic hoz e xpaiic zt alp Csk Gczgz Scroumklhpsy. Xcyi lyr tscp dlsaws rrph vlv, essf xszinle evlc hpfl gspoaio mm alp zfneytnhxtzb, alp xcuij evlc ozbhxpo khw yzh bwpo wu xsp fpkse khc. Ess prntrlre soz e rcshx ypuhxtgs prqwilrnp cu xsp Flh Ncczw Zcuhrtkoamzy, dlsaws kse efbwe th hrj xcyi, essf ecp bvx htzsmyr hv hzyoai esspv xzblc. Ld tvv xp, W dmww bvx ozbhxp xcuij ec alp zfneytnhxtzb, P gszczi ez upzp xcuij ec alp asywzy kos td wu rppr vj spzw, wz evl qzysf azyh ii elylr mj calpcg, tevp gbvp evl tpcgvr rph alp cshp xzblc.'

cipher_alpha = c_alpha(cipher)
print u"秘钥长度为:"
pre_10(cipher)

得出的结果排名靠前的都是5的倍数(栗子是'hello'),我们可以猜测秘钥长度为5

秘钥长度
2.破解单个秘钥
# 猜测单个秘钥得到的重合指数
def count_CI2(cipher,n):     # n 代表我们猜测的秘钥,也即偏移量
    N = [0.0 for i in range(26)]
    cipher = c_alpha(cipher)
    L = len(cipher)
    for i in range(L):     #计算所有字母的频数,存在数组N当中
        if (cipher[i].islower()):
            N[(ord(cipher[i]) - ord('a') - n)%26] += 1
        else:
            N[(ord(cipher[i]) - ord('A') - n)%26] += 1  
    CI_2 = 0
    for i in range(26):
        CI_2 += ((N[i] / L) * F[i])
    return CI_2

def one_key(cipher,key_len):
    un_cip = ['' for i in range(key_len)]   
    cipher_alpha = c_alpha(cipher)
    for i in range(len(cipher_alpha)):     # 完成分组工作
        z = i % key_len
        un_cip[z] += cipher_alpha[i]
    for i in range(key_len):
        print (i)
        pre_5_key(un_cip[i])     ####这里应该将5个分组的秘钥猜测全部打印出来

## 找出前5个最可能的单个秘钥
def pre_5_key(cipher):
    M = [(0,0.0) for i in range(26)]
    for i in range(26):
        M[i] = (chr(ord('a')+i),abs(0.065 - count_CI2(cipher,i)))
    M = sorted(M,key = lambda x:x[1])   #按照数组第二个元素排序

    for i in range(10):
        print (M[i])

key_len = 5   #输入猜测的秘钥长度
one_key(cipher,key_len)

得出的秘钥会按照可能性进行排序,排在第一位的字符取出得到'hello'。(图片太长了,所以只截取一部分)


单个秘钥

以上就是维吉尼亚秘钥的破解了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,612评论 5 471
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,345评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,625评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,022评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,974评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,227评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,688评论 3 392
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,358评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,490评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,402评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,446评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,126评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,721评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,802评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,013评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,504评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,080评论 2 341

推荐阅读更多精彩内容

  • 又到一年一度参观公路停车场的季节,为了赶个早,为了不让自己成为别人观光的对象,阿错先生凌晨3点半就醒了。 于是4点...
    卓橙爱读书阅读 236评论 0 3
  • 清晨,我刚进入校园,发现一大群学生在操场上嬉笑、追逐着什么。出于这么多年来的职业习惯,我立马走了过去一探究竟。结果...
    藕心竹节阅读 311评论 0 0
  • 竹亭鹊栖迟,茅舍鸡啼早。遥看顽童戏纸鹞,切切怜春好。 花开正妖娆,水漾徒清袅。若是天公纳俊豪,万万捎风到。 201...
    深蓝色木鱼阅读 337评论 8 4
  • 【阳春三月】20170516学习力践行记录day1 课已听,书已买,加课也已买,赶紧看,赶紧听,抓紧来践行。看...
    喜阳阳_49fa阅读 113评论 0 0
  • 我种了一个夏季的西红柿,呵呵
    如鹰展翅1阅读 85评论 0 0