破解维吉尼亚密码

时间:2019-10-07
本文章向大家介绍破解维吉尼亚密码,主要包括破解维吉尼亚密码使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

题目

密文为:

KCCPKBGUFDPHQTYAVINRRTMVGRKDNBVFDETDGILTXRGUD DKOTFMBPVGEGLTGCKQRACQCWDNAWCRXIZAKFTLEWRPTYC QKYVXCHKFTPONCQQRHJVAJUWETMCMSPKQDYHJVDAHCTRL SVSKCGCZQQDZXGSFRLSWCWSJTBHAFSIASPRJAHKJRJUMV GKMITZHFPDISPZLVLGWTFPLKKEBDPGCEBSHCTJRWXBAFS PEZQNRWXCVYCGAONWDDKACKAWBBIKFTIOVKCGGHJVLNHI FFSQESVYCLACNVRWBBIREPBBVFEXOSCDYGZWPFDTKFQIY CWHJVLNHIQIBTKHJVNPIST

1、Kasiski 测试法

首先我们用Kasiski 测试法确定密钥字的长度。密文串KC 在密文中的三处出现,起始位置在1,139,260,这三个数互素,所以未得到有效的信息

2、计算重合指数确定密钥长度

对该问题,使用如下代码计算其重合指数:

cipher = 'KCCPKBGUFDPHQTYAVINRRTMVGRKDNBVFDETDGILTXRGUD\
DKOTFMBPVGEGLTGCKQRACQCWDNAWCRXIZAKFTLEWRPTYC\
QKYVXCHKFTPONCQQRHJVAJUWETMCMSPKQDYHJVDAHCTRL\
SVSKCGCZQQDZXGSFRLSWCWSJTBHAFSIASPRJAHKJRJUMV\
GKMITZHFPDISPZLVLGWTFPLKKEBDPGCEBSHCTJRWXBAFS\
PEZQNRWXCVYCGAONWDDKACKAWBBIKFTIOVKCGGHJVLNHI\
FFSQESVYCLACNVRWBBIREPBBVFEXOSCDYGZWPFDTKFQIY\
CWHJVLNHIQIBTKHJVNPIST'

# print(len(cipher))
n = len(cipher)

def getNum(code):
    #统计各字符出现频率
    count={}
    length  = len(code)
    for i in range(len(code)):
        count[code[i]] = 0
    for i in range(len(code)):
        count[code[i]] += 1
    #print(count)
    #计算
    sum = 0
    for i in count:
        sum += count[i]*(count[i]-1)
    I = sum / (length*(length-1))
    # print(sum)
    # print((length*(length-1)))
    return I

# print(getNum(cipher))

def searchResult(code, k):
    print(k, "的结果:")
    step = int(n/k)
    sp = []
    for i in range(k):
        c = []
        for j in range(0, n, k):
            if j+i < n:
                c.append(code[j+i])
        c = ''.join(c)
        sp.append(c)
    for s in sp:
        if len(s) > 5:
            I = getNum(s)
            print(I)
            if I > 0.06:
                print('****************************************************')

for i in range(1, 10):
    searchResult(cipher, i)

输出结果为:

1 的结果:
0.040871838349583155
2 的结果:
0.038461538461538464
0.04712004562303963
3 的结果:
0.055941845764854614
0.048101673101673105
0.04826254826254826
4 的结果:
0.03725490196078431
0.04274239816408491
0.037578886976477335
0.04905335628227195
5 的结果:
0.04258121158911326
0.04302019315188762
0.032564450474898234
0.035278154681139755
0.04296698326549073
6 的结果:
0.06265664160401002
****************************************************
0.08376623376623377
****************************************************
0.04935064935064935
0.06493506493506493
****************************************************
0.04285714285714286
0.07337662337662337
****************************************************
7 的结果:
0.030612244897959183
0.044326241134751775
0.04343971631205674
0.040780141843971635
0.044326241134751775
0.044326241134751775
0.040780141843971635
8 的结果:
0.03322259136212625
0.04065040650406504
0.03368176538908246
0.04065040650406504
0.03948896631823461
0.04529616724738676
0.04065040650406504
0.0545876887340302
9 的结果:
0.051209103840682786
0.04267425320056899
0.06401137980085349
****************************************************
0.07539118065433854
****************************************************
0.04054054054054054
0.03453453453453453
0.04354354354354354
0.04804804804804805
0.042042042042042045

由此可以初步判断出密钥长度为6。

3、根据频率找到密钥字

这一步本想按照讲义上计算互重合指数的方法来做,但计算结果不是很尽人意,没有得到最终结果,使用代码如下:

n = len(cipher)
sp = []
for i in range(6):
    c = []
    for j in range(0, n, 6):
        if j+i < n:
            c.append(cipher[j+i])
    c = ''.join(c)
    sp.append(c)

#print(sp)

table = ['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']
#计算两个字符串的重合互指数
def getNum(s1, s2):
    count1 = getDict(s1)
    count2 = getDict(s2)
    sum = 0
    for l in table:
        sum += count1[l] * count2[l]
    MI = sum/(len(s1)*len(s2))
    return MI   


def getDict(s):
    count={}
    for i in range(len(table)):
        count[table[i]] = 0
    for i in range(len(s)):
        count[s[i]] += 1
    return count

def houyi(s, g):
    for i in range(len(s)):
        s =  s[:i] + chr((ord(s[i])-65+g)%26+65) + s[i+1:]
    return s

for i in range(6):
    for j in range(i+1, 6):
        for g in range(26):
            MI = getNum(sp[i], houyi(sp[j], g))
            if MI > 0.06:
                print(i, "and", j, "when", g, MI)

之后还是决定使用统计方法找出密钥字,得到统计结果:

{'A': 3, 'B': 0, 'C': 4, 'D': 0, 'E': 1, 'F': 2, 'G': 6, 'H': 2, 'I': 2, 'J': 6, 'K': 3, 'L': 0, 'M': 0, 'N': 4, 'O': 0, 'P': 4, 'Q': 7, 'R': 0, 'S': 0, 'T': 4,
'U': 0, 'V': 5, 'W': 4, 'X': 0, 'Y': 0, 'Z': 0}
{'A': 0, 'B': 0, 'C': 5, 'D': 2, 'E': 3, 'F': 8, 'G': 0, 'H': 0, 'I': 3, 'J': 1, 'K': 9, 'L': 0, 'M': 0, 'N': 1, 'O': 0, 'P': 0, 'Q': 0, 'R': 8, 'S': 1, 'T': 3,
'U': 2, 'V': 6, 'W': 1, 'X': 0, 'Y': 2, 'Z': 1}
{'A': 2, 'B': 3, 'C': 4, 'D': 5, 'E': 2, 'F': 5, 'G': 2, 'H': 0, 'I': 0, 'J': 3, 'K': 1, 'L': 6, 'M': 3, 'N': 1, 'O': 0, 'P': 2, 'Q': 3, 'R': 5, 'S': 3, 'T': 0,
'U': 0, 'V': 0, 'W': 1, 'X': 0, 'Y': 4, 'Z': 1}
{'A': 3, 'B': 1, 'C': 3, 'D': 8, 'E': 1, 'F': 0, 'G': 3, 'H': 0, 'I': 2, 'J': 1, 'K': 0, 'L': 2, 'M': 0, 'N': 2, 'O': 0, 'P': 5, 'Q': 2, 'R': 1, 'S': 3, 'T': 9,
'U': 1, 'V': 2, 'W': 4, 'X': 3, 'Y': 0, 'Z': 0}
{'A': 4, 'B': 4, 'C': 0, 'D': 0, 'E': 2, 'F': 0, 'G': 2, 'H': 5, 'I': 4, 'J': 0, 'K': 5, 'L': 3, 'M': 3, 'N': 2, 'O': 1, 'P': 4, 'Q': 0, 'R': 1, 'S': 0, 'T': 3,
'U': 1, 'V': 2, 'W': 2, 'X': 4, 'Y': 2, 'Z': 2}
{'A': 2, 'B': 6, 'C': 8, 'D': 1, 'E': 1, 'F': 1, 'G': 3, 'H': 7, 'I': 3, 'J': 0, 'K': 2, 'L': 0, 'M': 0, 'N': 0, 'O': 4, 'P': 0, 'Q': 1, 'R': 1, 'S': 8, 'T': 0,
'U': 0, 'V': 3, 'W': 2, 'X': 0, 'Y': 0, 'Z': 3}

利用课件中的频率表,经过尝试发现密钥字为crypto,解密结果为:

ILEARNEDHOWTOCALCULATETHEAMOUNTOFPAPERNEEDEDF ORAROOMWHENIWASATSCHOOLYOUMULTIPLYTHESQUAREFO OTAGEOFTHEWALLSBYTHECUBICCONTENTSOFTHEFLOORAN DCEILINGCOMBINEDANDDOUBLEITYOUTHENALLOWHALFTH ETOTALFOROPENINGSSUCHASWINDOWSANDDOORSTHENYOU ALLOWTHEOTHERHALFFORMATCHINGTHEPATTERNTHENYOU DOUBLETHEWHOLETHINGAGAINTOGIVEAMARGINOFERRORA NDTHENYOUORDERTHEPAPER

原文地址:https://www.cnblogs.com/chuaner/p/11631108.html