2016-12-05 11 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 быть нашим цифровым ключом (< 26 ради этого объяснения). Иметь c быть одним символом в p. Иметь I (c) be индекс c в p. Have fc (i) be a function, которая отображает индекс i на букву в алфавите. Иметь e (c) быть «зашифрованным» символом c.

Тогда:

е (с) = к (I (с) + к)

Или в простом английском языке: Каждый символов сдвигается на величину K. Поэтому это линейная подстановка, так как она всегда смещается на одну и ту же сумму, а символы заменяются.

Проблема с этим алгоритмом шифрования заключается в том, что вы действительно не скрещиваете открытый текст или добавляете энтропию. (В резких словах Цезарь-Шифр ближе к кодировке, а не к шифрованию).

Учитывая, что мы знаем, что все соответствующие буквы в нашем шифрованном тексте заменяют один и тот же символ обычного текста.

Это означает, что вы сможете выполнять статистический анализ на вашем Cipher-тексте и просто анализировать распределение букв. Различные звуки/буквы происходят разное количество раз.

Итак, как мы применяем эту технику?

Основываясь на вашем имени, я бы предположил, что вы немецкий, и я просто предполагаю, что ваш Cipher-текст тоже.

В немецком языке, наиболее часто встречающиеся буквы Е и 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)) 

последнего замечание: Так как это статистического анализ, этот подход работает лучше всего, если захваченный шифрованный текст долго.

Последнее примечание: Это немного неполное (и форматирование выглядит некрасиво, я нахожусь на мобильном телефоне.) Я бы рекомендовал этот german book от Klaus Schmeh для дальнейшего чтения.

+0

im собираюсь отредактировать код наверху хорошо it может открыть файл, расшифровать текст из этого файла и сохранить его в другом файле –

+0

Теперь вам нужно будет только скопировать и вставить ** 'find_key_from_cipher' и его содержащие символы и изменить ваш вызов на' decrypt (зашифрованный , find_key_from_cipher (зашифровано)). –

+0

Можете ли вы изменить мой код наверху, так что я больше ничего не путаю –