我一直在玩cryptocat这是一个有趣的在线聊天服务,它允许您使用密钥加密您的邮件,这样只有拥有相同密钥的人才能阅读您的邮件。该服务的一个有趣方面(在我看来)是这样一个事实,即使用您正在使用的密钥以外的密钥加密的文本仅显示为“[encrypted]”,而不是一堆垃圾密文。我的问题是,在Python中,是否有一种很好的方法来确定给定的文本是否是密文?我在这个例子中使用RC4,因为它是我能实现的最快的东西(基于Wikipedia上的伪代码。谢谢。
答案 0 :(得分:13)
没有保证的方法可以说明,但在实践中你可以做两件事:
检查许多非ascii字符(如果您希望人们发送英文文本)。
检查值的分布。在普通文本中,有些字母比其他字母更常见。但在加密文本中,所有角色的可能性几乎相同。
执行后者的一种简单方法是查看是否有任何字符出现超过(N / 256)+ 5 * sqrt(N / 256)次(总共有N个字符),在这种情况下它很可能一种自然语言(未加密)。
python中的(反转上面的逻辑,加密时给出“true”):
def encrypted(text):
scores = defaultdict(lambda: 0)
for letter in text: scores[letter] += 1
largest = max(scores.values())
average = len(text) / 256.0
return largest < average + 5 * sqrt(average)
数学来自平均数,是一个围绕平均值的高斯分布,方差等于平均值 - 它并不完美,但它可能足够接近。默认情况下(少量文本,当它不可靠时)这将返回false(对不起;早些时候我的版本不正确“max()”,其中小数字的逻辑是错误的方式)。
答案 1 :(得分:4)
每一个名副其实的密码都会产生看似完全随机的输出。无论您是处理加密文本还是处理某些未知协议的数据,您都可以利用这一事实进行快速测试。如果数据是加密的,那么您可以检查可以窃听的字节流中的字节值分布 - 如果所有值均匀分布,那么您很可能处理加密文本。
为了对决定越来越有信心,你可以将测试扩展到更复杂的东西,例如分析对的分布或字节的三元组等。
另一方面,您还可以将您感兴趣的特定语言的digrams和trigrams的统计数据与您观察到的数据中的事件进行比较(另请参阅here)。如果您的数据行为相似,那么您更有可能观察纯文本。
答案 2 :(得分:0)
一种说法是填充。在邮件末尾添加标准填充。如果解密的消息没有以标准填充结束,则使用错误的密钥对其进行解密。反过来并不保证,但通常是正确的。