Python无密钥破解Vigenere密码示例

【这是密码学课上的一个作业题】

Vigenere密码即为传统多表代换密码,使用一密钥词对每个明文字母选择一个字母表来加密,如果到了密钥词的最后一个字母,则从头开始继续。

举例如下,比如使用密钥deceptive加密这样一段话:we are discovered save yourself

Key d e c e p t i v e d e c e p t i v e d e c e p t i v e
PlainText w e a r e d i s c o v e r e d s a v e y o u r s e l f
CipherText Z I C V T W Q N G R Z G V T W A V Z H C Q Y G L M G J

加密之后密文即为:ZICVTWQNGRZGVTWAVZHCQYGLMGJ ,加密的方法即明文字母根据密钥字母向后平移不同的位数。与单字母表加密方法不同,单字母表每个明文字母向后平移相同的位数。所以单字母表加密保留了明文的英文字母的统计特性,由于英文字母的相对使用频率是固定的统计值,所以很容易被破译。

Vigenere密码因为需要猜测更多的字母表,并且频率分布特性也更加平坦,所以使得密码破译相对困难。

但是可以通过分析密文中的重复性来猜测密钥的长度,因为如果两个相同明文序列之间的距离是密钥词长度的整数倍,那么产生的密文序列也是相同的。再根据英文字母的频率分布特性,即可以实现破解。

这里即使用这种方法猜解Vigenere密码的密钥并实现破译。

密文如下,保存于vigenereCipherText文件中

wubefiqlzurmvofehmymwtixcgtmpifkrzupmvoirqmmwozmpulmbnyvqqqmvmvjleymhfefnzpsdlppsdlpevqmwcxymdavqeefiqcaytqowcxymwmsemefcf

wyeyqetrliqycgmtwcwfbsmyfplrxtqyeexmruluksgwfptlrqaerluvpmvyqycxtwfqlmtelsfjpqehmozciwciwfpzslmaeziqvlqmzvppxawcsmzmorvgvvqszetrlqz

pbjazvqiyxewwoiccgdwhqmmvowsgntjpfppaybiybjutwrlqklllmdpyvacdcfqnzpifppksdvptidgxmqqvebmqalkezmgcvkuzkizbzliuammvz

编写程序如下:

#File vigenere.py
def decode(cipherText):
    '''解密'''
    length = findKeyLen(cipherText) #得到密钥长度
    key = findKey(cipherText,length) #找到密钥
    keyStr = ''
    for k in key:
        keyStr+=k
    print('the Key is:',keyStr)
    plainText = ''
    index = 0
    for ch in cipherText:
        c = chr((ord(ch)-ord(key[index%length]))%26+97)
        plainText += c
        index+=1
    return plainText
        
def openfile(fileName):
    '''读取文件'''
    file = open(fileName,'r')
    text = file.read()
    file.close();
    text = text.replace('\n','')
    return text

def findKeyLen(cipherText):
    '''寻找密钥长度'''
    length = 1
    maxCount = 0
    for step in range(1,11):#假定密钥长度在1到10之间
        count = 0
        for i in range(step,len(cipherText)-step):
            if cipherText[i] == cipherText[i+step]:
                 count += 1
        print(count)
        if count>maxCount:
            maxCount = count
            length = step
    return length

def findKey(text,length):
    '''找出密钥'''
    key = []
    #定义字母表频率列表
    alphaRate =[0.08167,0.01492,0.02782,0.04253,0.12705,0.02228,0.02015,0.06094,0.06996,0.00153,0.00772,0.04025,0.02406,0.06749,0.07507,0.01929,0.0009,0.05987,0.06327,0.09056,0.02758,0.00978,0.02360,0.0015,0.01974,0.00074]
    matrix =textToList(text,length)
    for i in range(length):
        w = [row[i] for row in matrix] #取出每组密文
        #print('w:',w)
        li = countList(w) #统计w中a-z出现的频率
        powLi = [] #算乘积
        for j in range(26):
            Sum = 0.0
            for k in range(26):
                Sum += alphaRate[k]*li[k]
            powLi.append(Sum)
            li = li[1:]+li[:1]#循环移位
        Abs = 100
        ch = ''
        for j in range(len(powLi)):
             if abs(powLi[j] -0.065546)<Abs:
                 Abs = abs(powLi[j] -0.065546)
                 ch = chr(j+97)
        key.append(ch)
    return key                

def countList(lis):
    '''统计列表中a-z出现的频率'''
    li = []
    alphabet = [chr(i) for i in range(97,123)]
    for c in alphabet:
        count = 0
        for ch in lis:
            if ch == c:
                count+=1
        li.append(count/len(lis))
    return li
        
def textToList(text,length):
    '''按密钥长度将text分组'''
    textMatrix = []
    row = []
    index = 0 
    for ch in text:
        row.append(ch)
        index += 1
        if index % length ==0:
            textMatrix.append(row)
            row = []
    return textMatrix


#按行输出矩阵
def printTextMatrix(matrix):
    for i in range(len(matrix)):
        print(matrix[i])


if __name__ == '__main__':
    cipherText = openfile('vigenereCipherText.txt')
    print('cipherText:\n',cipherText)
    print('====================')
    plainText= decode(cipherText)
    print('====================')
    print('plainText:\n',plainText)

运行结果:

Key:

emily

plainText:

 sittheedownandhavenoshamecheekbyjowlandkneebykneewhatcareiforanynamewhatfororderordegreeletmescrewtheeupapegletmeloosethytongu

ewithwinecallestthouthatthingalegwhichisthinnestthineorminethoushaltnotbesavedbyworksthouhastbeenasinnertooruinedtrunksonwitheredforksem

ptyscarecrowsiandyoufillthecupandfillthecanhavearousebeforethemorneverymomentdiesamaneverymomentoneisborn

你可能感兴趣的:(python,破解,vigenere)