• 破解维吉尼亚密码


    题目

    密文为:

    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
    
  • 相关阅读:
    loadrunner(预测系统行为和性能的负载测试工具)
    SOA(面向服务的架构)
    Acunetix Web Vulnerability Scanner(WVS)(Acunetix网络漏洞扫描器)
    Redis主从复制
    Redis启动方式
    Struts2.5以上版本There is no Action mapped for namespace [/] and action name [userAction_login] associated with context path []
    使用Slf4j集成Log4j2构建项目日志系统的完美解决方案
    Write operations are not allowed in read-only mode (FlushMode.MANUAL): Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker from transaction definition.
    intellij 编译 springmvc+hibernate+spring+maven 找不到hbm.xml映射文件
    MySQL8连接数据库
  • 原文地址:https://www.cnblogs.com/chuaner/p/11631108.html
Copyright © 2020-2023  润新知