1. 程式人生 > >仿射密碼之加解密及破解

仿射密碼之加解密及破解

【題目】

1) 實現仿射密碼,具體要求:

A. 實現仿射密碼加密過程,由使用者輸入金鑰,可以對任意輸入的明文進行加密;

B. 根據使用者輸入的加密金鑰,自動生成解密金鑰,並能對加密密文進行解密;

C. 實現仿射密碼破解程式(窮舉),能對任意輸入的密文進行解密

【實現程式碼】

# -*- coding: utf-8 -*-
"""
Created on Sun Dec 17 20:03:09 2017
仿射密碼加密, 解密, 破解
@author: HP
"""
from string import ascii_lowercase as lowercase
from string import ascii_uppercase as uppercase

frequencyTable = [4, 19, 14, 0, 13, 8, 17, 18, 7, 3, \
                  11, 2, 20, 12, 15, 24, 22, 6, 1, 21, \
                  10, 23, 9, 16, 25]

# 刪除預留的標點

#文字過濾
def text_filter (text):
    text = text.lower()
    result = ""
    for i in range(len(text)):
        if lowercase.find(text[i]) != -1:
            result += text[i]
    return result
    
#加密部分
def encryption(plaintext, k1, k2):
    plaintext = text_filter(plaintext)
    result = ""
    for i in range(len(plaintext)):
        index = lowercase.find(plaintext[i])
        c_index = (k1*index+k2)%26
        result += uppercase[c_index]
    return result

#解密部分
def get_inverse(a, b): 
    """
    #求a關於模b的逆元
    """
    if(a==1 and b==0):
        x = 1
        y = 0
        return x, y
    else:
        xx, yy = get_inverse(b, a%b)
        x = yy
        y = xx - a//b*yy
        return x, y

def Decryption(k1, k2, ciphertext):
    k3 = get_inverse(k1, 26)[0]
    result = ""
    for i in range(len(ciphertext)):
        index = uppercase.find(ciphertext[i])
        p_index = k3*(index- k2)%26
        result += lowercase[p_index]
    return result
    
#破解部分
def get_frequencyTable(ciphertext): 
    """
    返回一個列表;
    取得密文的字母頻率表, 按字母出現頻率從大到小排列, 值為字母對應的索引
    """
    #取得字母頻率字典
    count = {}
    for i in range(len(ciphertext)):
        count[ciphertext[i]] = count[ciphertext[i]] + 1 if ciphertext[i] in count else 1

    #把字典轉換為列表, 並且對其排序, 最終得到返回值
    items = count.items()
    items_list = [[item[1], item[0]]for item in items]
    items_list1 = sorted(items_list, reverse = True)
    chara_list = [item[1] for item in items_list1]
    return list(map(lambda x: uppercase.index(x),chara_list))
    
# 根據a,b,c,d獲取金鑰K1
def get_k1(a, b, c, d):
    i = 0
    while True:
        k1 = ( float(a - d - 26 * i) / float(b - c) )
        if k1 < -26 or k1 > 26:
            return None
        if isinstance(k1, int):
            return k1
        i = i + 1
        
def get_abcd(list1, list2):
    list3 = list(map(lambda x, y: [x, y], list1, list2))
    result = []
    for i in range(len(list3)):
        for j in range(i+1, len(list3)):
            result.append(list3[i]+list3[j])
    return result
    
def crack():
    list1 = ['u','v','w']
    list2 = ['x','y','z']
    list22 = list(list2)
    result = []
    count = 0
    while count<6:
        for item in get_abcd(list1, list22):
            k1 = get_k1(*item)
            if k1 is None or gcd(k1, 26) != 1:
                break
            k2 = int(d - c * k1) % 26
            result.append( decryption(Cs, t, k3) )
        if(count%2==1):
            first = list2.pop(0)
            list2.append(first)
            list22 = list(list2)
        else:
            list22[1], list22[2] = list22[2], list22[1]
        count += 1        
    

if __name__ == '__main__':
    ciphertext = input("enter the ciphertext: ")
    print(Decryption(7, 3, ciphertext))