文章参考了维吉尼亚密码-CTFwp2_dqmctf-CSDN博客 大佬的代码
这里只记录了根据kasiski方法估计密钥长度以及通过密钥长度和密文推测明文,其他内容可以自行百度
craking_virginia
-
kasiski确认密钥长度
'''
维吉尼亚密码
'''
import math
def kasiski(ciphertext):
dict = {}
for i in range(len(ciphertext) - 2):
#每次遍历都会向右移动一个长度为3的字符串
item = ciphertext[i:i+3]
if item in dict:
continue
if ciphertext.count(item) >= 4:
dict[item] = []
j = i+3
while j <= len(ciphertext) - 2:
#从第二个item的位置开始找,如果找到的到返回索引,找不到就返回-1
pos = ciphertext.find(item,j)
if pos > 0:
dict[item].append(pos - i)
j = pos + 3
else:
break
keylen = []
for item in dict:
x = math.gcd(dict[item][0],dict[item][1])
for i in dict[item][2:]:
x = math.gcd(x,i)
if x > 2:
keylen.append(x)
print(keylen)
if __name__ == '__main__':
# ciphertext = input('请输入明文: ')
ciphertext = 'faprepeapmsstwmcxdfwfaprepeapmsstwmcxdfwfaprepeapmsstwmcxdfwfaprepeapmsstwmcxdfwfaprepeapmsstwmcxdfwdteprdxcrsnlwtghealcegnzyahzeleutgircdgebpawxhpidtogidiqjxaqecixektglhispdwanhavokxoisiwpylixxetthzgctgpbptgtinrttwucrzrtgdwpaqapxodqtkogyfwthxxtlnheypxseleqpwpaahzlahxewfpcdpiztprgapyhsspgmdqtnohpbmythdqeriwpcsttxxowpgibttysuicfqbtgphbnrcmtxrdedxslwspndxhtqlplheweswtoaiiwrslsrzpogxykihffmtthtqpaneleqtdxagdfrdetcgecixsrtpngugpeitwpyxhtqlpljhphaiucenrtelaczdxobtemcjazysitdxicvmcsrxprtxhewicvpvmpcjxhtizrgjteaihitrgcpeyrtdqmthrzrttcewcdcqmrbhelaiisiwdgwhcjemelawlwcdbpeldcraanucsmiwppepisirpcopartdzagxpxyiwlxwphnsmbdyesgtniniajesiwpwtwtqivtgysvphdicgteedxslwspndmsxidvasxnelantqpgdgidhnyxaritgfdpxensjymqjtvriiiphrphnleaulfrxrrmvtcelaiismsxhdypeddididxektisibpawjahipvacsavokxoitwtqvetztgkhepgipatwthatoeqtnohpbhmtwbzveedhirxixeycdefehjctrxhtrgiwlxgdpwoetepvsaxvibjuqsnpgpynwpatyhelmnvdlpkttairetovordyxrtglwspxoxhtqlmlprewsiglrgtajahxaphacxdlkttairiwzqahhzvechprasbtxttsrpodbtpyiwlxiilzylsecsbpqwcrthfptxcxsrthaicipnylpgrsaahlwavdlpkttairndflakteslxkpaiiweleupnxtwpexhtbloeghnvepipfaaadjogisibtcpjiidqwtgxvirhwpwaxsmifdgppepktrgrdainwprinudcwojisoogtlfuidfxfxtwhpapjirhwlzepadswtxrlesxyaiiwnviixnmsbblryhpjmnvisibpawmsidzpivweensisirtuzvewpchtdrzrtgdwmthqtkacstxsidzpivwenaepywjxytrelhlkecrjuudiphbgpkmlxpyjogllvdtstpsdclwspntrgtpcpitgelihbzrtwlsmltheviztcvikpwhohpthiihzertsesoupcahtcvmcztonojgyelxhewaiisimpxytrthdgeciciicnzoowpxehpkpfetcrmvtcelerwlrctizxrndfxtwtqivtgysvpucsmiwptecpwxyhezxwxisxhtptqouwtxtxcrwptrtelipckeihtrtwtrsaahzjagupahpkpfetclfltizwcdgpqogtelacutzedjesfityeliwzygwismsbpjlaktwmtiapxosdhmtwisiqjpwmtndqxhtqlplejedasbtxsiwlxtwtmelaxdsniwppivwewistzjfxulwtdvcemlttkhigpuuxgpqecimythpjwiixdroqxrkegisenegpzidjdfaaadxhtrzrtgdgirhnzzegisibpawelhdsespczjfexeghsxxinhxzricsfwtgntrsxspvshpjmtbpjfecdnsicrthecrpxhpiapantcwfgdxfrpotpsedywogtofypsthahgtzaactoewpgibttyemdcrxhtqlplhbzwtkdnmftgzysrgtxirhelehpximxvsxgduzvtwtavaxhphihwphojiqsriwpfaaamcbtrvlabdyiouisimpxytlpnpvsjhphtdecsmdipedxslwefjttmtce'
kasiski(ciphertext)
-
求得密钥每个字母
重合指数法
f1 = [p(a字母出现的概率).r(a在总文本中出现的次数)]/文本的长度
f2 = [p(b字母出现的概率).r(b在总文本中出现的次数)]/文本的长度
......
fz = [p(z字母出现的概率).r(z在总文本中出现的次数)]/文本的长度
重合指数 =[ f1 + f2 +....... + fz]/文本的长度
如果重合指数是0.065左右则说明是一个有意义的文本,反之则是一个随机文本
'''
维吉尼亚密码已知密钥长度,爆破密钥
'''
def getkey(keylen,ciphertext):
#1.根据网上的对子a-z出现频率的统计,创建一个列表p,用于后面计算重合指数
p = [0.08167, 0.01492, 0.02782, 0.04253, 0.12702, 0.02228, 0.02015, 0.06094, 0.06966, 0.00153, 0.00772, 0.04025,
0.02406, 0.06749, 0.07507, 0.01929, 0.00095, 0.05987, 0.06327, 0.09056, 0.02758, 0.00978, 0.02360, 0.00150,
0.01974, 0.00074]
#2.根据密钥的长度对密文内容进行分组
for i in range(keylen):
f_sum_list = []
after_div = ciphertext[i::keylen].lower()
#5.设置for循环,计算偏移量(相当于凯撒单表解密)
for offset in range(26):
#3.分组以后统计各组a-z在各自组中出现的次数
alp_sta_list = []
for x in range(26):
alp_sta = after_div.count(chr(97+(x+offset)%26))
alp_sta_list.append(alp_sta)
# print(alp_sta_list)
#4.根据alp_sta_list和p计算重合指数f
f_sum = 0
for x in range(26):
f = (alp_sta_list[x]*p[x])/len(after_div)
f_sum = f_sum + f
f_sum_list.append(f_sum)
key = chr(97+f_sum_list.index(max(f_sum_list)))
print(key,end='')
if __name__ == '__main__':
keylen = 5
ciphertext = 'faprepeapmsstwmcxdfwfaprepeapmsstwmcxdfwfaprepeapmsstwmcxdfwfaprepeapmsstwmcxdfwfaprepeapmsstwmcxdfwdteprdxcrsnlwtghealcegnzyahzeleutgircdgebpawxhpidtogidiqjxaqecixektglhispdwanhavokxoisiwpylixxetthzgctgpbptgtinrttwucrzrtgdwpaqapxodqtkogyfwthxxtlnheypxseleqpwpaahzlahxewfpcdpiztprgapyhsspgmdqtnohpbmythdqeriwpcsttxxowpgibttysuicfqbtgphbnrcmtxrdedxslwspndxhtqlplheweswtoaiiwrslsrzpogxykihffmtthtqpaneleqtdxagdfrdetcgecixsrtpngugpeitwpyxhtqlpljhphaiucenrtelaczdxobtemcjazysitdxicvmcsrxprtxhewicvpvmpcjxhtizrgjteaihitrgcpeyrtdqmthrzrttcewcdcqmrbhelaiisiwdgwhcjemelawlwcdbpeldcraanucsmiwppepisirpcopartdzagxpxyiwlxwphnsmbdyesgtniniajesiwpwtwtqivtgysvphdicgteedxslwspndmsxidvasxnelantqpgdgidhnyxaritgfdpxensjymqjtvriiiphrphnleaulfrxrrmvtcelaiismsxhdypeddididxektisibpawjahipvacsavokxoitwtqvetztgkhepgipatwthatoeqtnohpbhmtwbzveedhirxixeycdefehjctrxhtrgiwlxgdpwoetepvsaxvibjuqsnpgpynwpatyhelmnvdlpkttairetovordyxrtglwspxoxhtqlmlprewsiglrgtajahxaphacxdlkttairiwzqahhzvechprasbtxttsrpodbtpyiwlxiilzylsecsbpqwcrthfptxcxsrthaicipnylpgrsaahlwavdlpkttairndflakteslxkpaiiweleupnxtwpexhtbloeghnvepipfaaadjogisibtcpjiidqwtgxvirhwpwaxsmifdgppepktrgrdainwprinudcwojisoogtlfuidfxfxtwhpapjirhwlzepadswtxrlesxyaiiwnviixnmsbblryhpjmnvisibpawmsidzpivweensisirtuzvewpchtdrzrtgdwmthqtkacstxsidzpivwenaepywjxytrelhlkecrjuudiphbgpkmlxpyjogllvdtstpsdclwspntrgtpcpitgelihbzrtwlsmltheviztcvikpwhohpthiihzertsesoupcahtcvmcztonojgyelxhewaiisimpxytrthdgeciciicnzoowpxehpkpfetcrmvtcelerwlrctizxrndfxtwtqivtgysvpucsmiwptecpwxyhezxwxisxhtptqouwtxtxcrwptrtelipckeihtrtwtrsaahzjagupahpkpfetclfltizwcdgpqogtelacutzedjesfityeliwzygwismsbpjlaktwmtiapxosdhmtwisiqjpwmtndqxhtqlplejedasbtxsiwlxtwtmelaxdsniwppivwewistzjfxulwtdvcemlttkhigpuuxgpqecimythpjwiixdroqxrkegisenegpzidjdfaaadxhtrzrtgdgirhnzzegisibpawelhdsespczjfexeghsxxinhxzricsfwtgntrsxspvshpjmtbpjfecdnsicrthecrpxhpiapantcwfgdxfrpotpsedywogtofypsthahgtzaactoewpgibttyemdcrxhtqlplhbzwtkdnmftgzysrgtxirhelehpximxvsxgduzvtwtavaxhphihwphojiqsriwpfaaamcbtrvlabdyiouisimpxytlpnpvsjhphtdecsmdipedxslwefjttmtce'
getkey(keylen,ciphertext)