關(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ù)

其中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

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)了,所以只截取一部分)

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