2016-12-05 128 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

你可以在顶部编辑我的代码,所以我不会再搞砸了 –