2016-12-05 124 views
-2

嘿傢伙,如果你看看我的代碼下面你將能夠看到,我能夠創建一個程序,可以打開一個文件解碼文件的內容並將其保存到另一個文件中,但我需要每次都輸入密鑰,但如果我不知道他們的密鑰,我該如何使用頻率分析來計算密鑰。凱撒密碼不知道密鑰

import sys 

def decrypt(cipher, key): 

plain = "" 
for index in range(len(cipher)): 
    if cipher[index].isalpha(): 

     if cipher[index].isupper(): 
      plain = plain + chr((ord(cipher[index]) - 64 - key) % 26 + 64) 


     elif cipher[index].islower(): 
      plain = plain + chr((ord(cipher[index]) - 96 - key) % 26 + 96) 

    else: 
      plain = plain + cipher[index] 

return plain 

in_filename = sys.argv[1] 
key = int(sys.argv[2]) 
out_filename = sys.argv[3] 

with open(in_filename, "r") as f: 
    encrypted = f.read() 

decrypted = decrypt(encrypted, key) 

with open(out_filename, "w+") as f: 
    f.write(decrypted) 
+4

幫助什麼? –

+0

抱歉,我們需要更多信息來幫助您...您是否已經有一些可以發佈的代碼? – Dadep

+0

如果您使用已知語言解密文本,則可以嘗試每個可能的密鑰,並查看該語言的單詞列表中有多少個結果單詞。 –

回答

1

凱撒密碼是一個線性替換密碼。 說明:

p是您的明文。 有k是我們的數字鍵(爲了說明的緣故,<)。 有cp中的一個字符。 有I(c)的索引c的p。 有fc(i)是一個函數,它將索引i映射到它的字母表中的字母。 有e(c)是c的加密字符。

然後:

E(C)= FC(I(C)+ k)的

或者簡單的英語:每個字符得到由的ķ的值移位。因此它是一個線性替換,因爲它總是被移動相同的數量並且字符被替換。

這個加密算法的問題是,你不真正加密明文或添加熵。 (用粗俗的話來說,凱撒密碼更接近編碼而不是加密)。

鑑於此,我們知道我們的密文中的所有匹配字母都替代完全相同的純文本字符。

這意味着,您將能夠對密文進行統計分析,並簡單地分析字母分佈。不同的聲音/字母出現不同的次數。

那麼我們該如何應用這種技術?

根據你的名字,我想你是德國人,我只是假設你的密碼文本也是如此。

在德國,最常見的字母是E和I.

我們快到了!

現在,您可以簡單地找到密文中最常見的字母,然後計算該字母與E之間的差異(當然,它們的索引之間的差異)。這會讓你獲得祕密密鑰!

這裏是一個代碼示例:

""" 
This module aims to break Caesar-ciphers from German plaintext 
based  on statistics of letter distribution. 

The caesar cipher is a character substitution algorithm. 
Bob chooses a number as the key n. 
Bob then shifts every character of the plain-text by n, cycling 
through the entire alphabet. 

e.g.: if n = 3: "ABC" -> "DEF". 

Since it has a very small keyspace (26^1), it can be easily broken, 
and Mallory could even guess or bruteforce the key. 
(Note: You could choose a number higher than 26. However, this won't 
increase your keyspace since any number x will 
be reduced to 1-26. See: (x - (26*(x // 26)). 

Common letters in the german language are (in descending order): 
"E","N","I","S","R" (subject to verification) 

The statistical approach works well for long sentences since one has 
a greater samplesize for distribution analysis. 
If two or more letters appear the same amount of times, you have to 
check which key is actually correct, either 
by simply reading the outputs or running them against a 
distribution_dict of that language. 

""" 

ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 
SPECIAL_CHARS = " ,.-;:_?!=" 

def encrypt(plain_text, key): 
    """ 
    Encrypts plaintext using a caesar. 

    :param plain_text: The plaintext 
    :param key: The key (Integer) 
    :return: The cipher-text 
    """ 
    cipher_text = "" 
    for letter in plain_text: 
     if letter in SPECIAL_CHARS: 
      cipher_text += letter 
      continue 
     index = ALPHABET.find(letter.upper()) 
     new_index = flatten(index + key) 
     cipher_text += ALPHABET[new_index] 
    return cipher_text 

def decrypt(cipher_text, key=None): 
    """ 
    This function decrypts plaintext. If no key is specified, it 
    will be found using distribution analysis. 
    :param cipher_text: The cipher-text 
    :param key: The key 
    :return: the plain-text 
    """ 
    if key is None: 
     key = find_key_from_cipher(cipher_text) 

    plain_text = "" 
    for letter in cipher_text: 
     #Skipping special characters (incomplete solution) 
     if letter in SPECIAL_CHARS: 
      plain_text += letter 
      continue 
     index = ALPHABET.find(letter.upper()) 
     new_index = flatten(index - key) 
     plain_text += ALPHABET[new_index] 

    return plain_text 

def flatten(number) : 
    """ 
    Flattens the key back to be in range(1,26) 
    :param number: 
    :return: 
    """ 
    return number - (26*(number//26)) 


def find_key_from_cipher(cipher_text): 
    index_of_most_common_letter = 4 #Index of 'e' 

    #Calculate distribution 
    distribution_dict = analyse_letter_distribution(cipher_text) 
    #Get common letters 
    common_letters = sorted(distribution_dict, key=distribution_dict.get, reverse=True) 

    #Use most common letter to get key 
    key = ALPHABET.find(common_letters[0].upper()) - index_of_most_common_letter 
    return key 

def analyse_letter_distribution(cipher_text): 
    distribution_dict = {} 
    for letter in cipher_text: 
     if letter in SPECIAL_CHARS: 
      continue 
     if letter not in distribution_dict: 
      distribution_dict[letter] = 1 
     else: 
      distribution_dict[letter] += 1 
    if len(distribution_dict.values()) != len(distribution_dict.values()): 
     print("Multiple letters appear the same amount of times! Uh oh.") 
    return distribution_dict 


    if __name__ == "__main__": 
     secret = encrypt("This sentence is encrypted. Encryption is broken  by using awesome encryption algorithms!",5) 
     print(decrypt(secret)) 

最後一個音符:由於這是一個統計分析,這種方法效果最好,如果捕獲的密文長。

最後一個註釋:這個描述有點不完整(格式看起來很醜,我在手機上)。我強烈推薦Klaus Schmeh的german book作進一步閱讀。

+0

即時編輯頂部代碼好吧 它能夠打開一個文件解密該文件中的文本並將其保存到另一個文件 –

+0

現在,您只需**複製並粘貼**'find_key_from_cipher'及其包含的符號,並將您的調用更改爲'decrypt(encrypted ,find_key_from_cipher(encrypted))'。 –

+0

你可以在頂部編輯我的代碼,所以我不會再搞砸了 –