python實(shí)現(xiàn)維吉尼亞秘鑰破解

關(guān)于維吉尼亞密碼,百度百科中有著較為詳細(xì)的描述:
維吉尼亞密碼——百度百科
維吉尼亞密碼的原理與凱撒密碼類似,其實(shí)是凱撒的一種強(qiáng)化和變形,通過使加密相同明文的秘鑰不同,來掩蓋字符的頻率。
舉個(gè)栗子:
秘鑰為"hello",明文為"today when people ......",通過秘鑰加密后結(jié)果如下:

加密

可以看到相同的明文e,經(jīng)過不同的字符加密之后變成了不同的密文,掩蓋了明文字符e的字符頻率。
但也不是找不到字符頻率,我們可以發(fā)現(xiàn),將用"h"字符加密的明文取出之后,就變成了普通的凱撒加密,這是可以通過字符頻率分析來破解的。
這就為維吉尼亞秘鑰的破解帶來了思路。

思路與過程

1.破解秘鑰長(zhǎng)度N。
2.將密文分成N組,逐個(gè)破解秘鑰。

用到的數(shù)學(xué)公式:重合指數(shù)

重合指數(shù)

其中fi為每個(gè)字符在英文當(dāng)中的頻率。fi^2則表示連續(xù)取出兩個(gè)相連的字符,它們相同的概率。英文中對(duì)26種情況求和的統(tǒng)計(jì)結(jié)果約為0.065。
Ni/N為密文中某個(gè)字符占密文的比例,假設(shè)秘鑰長(zhǎng)度為key_len,如果key_len組密文中的重合指數(shù)IC1也都與0.065接近,那么就可以推測(cè)key_len是秘鑰長(zhǎng)度了。

當(dāng)秘鑰長(zhǎng)度key_len知道以后,我們將密文分成key_len個(gè)組,計(jì)算每個(gè)分組的IC2。
舉個(gè)栗子:如果第一個(gè)分組都是用b字符進(jìn)行加密,那么a字符的頻率會(huì)轉(zhuǎn)移到b字符上,c字符的頻率會(huì)轉(zhuǎn)移到d字符上......我們也做這種相應(yīng)的轉(zhuǎn)移,讓b字符在密文的頻率(N1/L)和a字符在英文的頻率f0相乘,當(dāng)然這只是其中一種猜測(cè)。我們將這26種字符可能都列出來,最接近IC的一定是用b字符加密的那一組。

讀者如果想知道詳細(xì)的資料,可以去網(wǎng)上查找關(guān)于重合指數(shù)的詳細(xì)內(nèi)容,這里也給出一個(gè)博客。
密碼學(xué)原理-篇1:重合指數(shù)

步驟

1.破解秘鑰長(zhǎng)度

首先要有需要破解的密文,密文長(zhǎng)度要足夠,否則無法破解,筆者給大家一個(gè)栗子。

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.'

字符頻率大家在網(wǎng)上也都可以搜得到。

'''
'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

# 計(jì)算cipher的重合指數(shù)
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):     #計(jì)算所有字母的頻數(shù),存在數(shù)組N當(dāng)中
            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

# 計(jì)算秘鑰長(zhǎng)度為 key_len 的重合指數(shù)
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

## 找出最可能的前十個(gè)秘鑰長(zhǎng)度
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])   #按照數(shù)組第二個(gè)元素排序
    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"秘鑰長(zhǎng)度為:"
pre_10(cipher)

得出的結(jié)果排名靠前的都是5的倍數(shù)(栗子是'hello'),我們可以猜測(cè)秘鑰長(zhǎng)度為5

秘鑰長(zhǎng)度
2.破解單個(gè)秘鑰
# 猜測(cè)單個(gè)秘鑰得到的重合指數(shù)
def count_CI2(cipher,n):     # n 代表我們猜測(cè)的秘鑰,也即偏移量
    N = [0.0 for i in range(26)]
    cipher = c_alpha(cipher)
    L = len(cipher)
    for i in range(L):     #計(jì)算所有字母的頻數(shù),存在數(shù)組N當(dāng)中
        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])     ####這里應(yīng)該將5個(gè)分組的秘鑰猜測(cè)全部打印出來

## 找出前5個(gè)最可能的單個(gè)秘鑰
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])   #按照數(shù)組第二個(gè)元素排序

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

key_len = 5   #輸入猜測(cè)的秘鑰長(zhǎng)度
one_key(cipher,key_len)

得出的秘鑰會(huì)按照可能性進(jìn)行排序,排在第一位的字符取出得到'hello'。(圖片太長(zhǎng)了,所以只截取一部分)


單個(gè)秘鑰

以上就是維吉尼亞秘鑰的破解了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 又到一年一度參觀公路停車場(chǎng)的季節(jié),為了趕個(gè)早,為了不讓自己成為別人觀光的對(duì)象,阿錯(cuò)先生凌晨3點(diǎn)半就醒了。 于是4點(diǎn)...
    卓橙愛讀書閱讀 302評(píng)論 0 3
  • 清晨,我剛進(jìn)入校園,發(fā)現(xiàn)一大群學(xué)生在操場(chǎng)上嬉笑、追逐著什么。出于這么多年來的職業(yè)習(xí)慣,我立馬走了過去一探究竟。結(jié)果...
    藕心竹節(jié)閱讀 351評(píng)論 0 0
  • 竹亭鵲棲遲,茅舍雞啼早。遙看頑童戲紙鷂,切切憐春好。 花開正妖嬈,水漾徒清裊。若是天公納俊豪,萬萬捎風(fēng)到。 201...
    深藍(lán)色木魚閱讀 387評(píng)論 8 4
  • 【陽春三月】20170516學(xué)習(xí)力踐行記錄day1 課已聽,書已買,加課也已買,趕緊看,趕緊聽,抓緊來踐行???..
    喜陽陽_49fa閱讀 156評(píng)論 0 0
  • 我種了一個(gè)夏季的西紅柿,呵呵
    如鷹展翅1閱讀 120評(píng)論 0 0

友情鏈接更多精彩內(nèi)容