5

我一直在玩cryptocat,这是一个有趣的在线聊天服务,它允许您使用密钥加密您的消息,这样只有拥有相同密钥的人才能阅读您的消息。该服务的一个有趣的方面(在我看来)是这样一个事实,即使用您正在使用的密钥以外的密钥加密的文本仅显示为“[加密]”,而不是一堆垃圾密文。我的问题是,在 Python 中,有没有一种好方法可以确定给定的一段文本是否是密文?我在这个例子中使用了 RC4,因为它是我可以实现的最快的东西(基于Wikipedia上的伪代码。谢谢。

4

3 回答 3

16

没有保证的方式来告诉,但在实践中你可以做两件事:

  1. 检查许多非 ASCII 字符(如果您希望人们发送英文文本)。

  2. 检查值的分布。在普通文本中,某些字母比其他字母更常见。但在加密文本中,所有字符的可能性都差不多。

执行后者的一种简单方法是查看是否有任何字符出现超过 (N/256) + 5 * sqrt(N/256) 次(总共有 N 个字符),在这种情况下,它可能是一种自然语言(未加密)。

在python中(颠倒上面的逻辑,加密时给出“真”):

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()”版本不正确,它的逻辑是错误的小数字)。

于 2011-08-09T18:26:55.190 回答
4

每个名副其实的密码都会产生看似完全随机的输出。无论您是在处理加密文本还是遵循某些未知协议的数据,您都可以利用这一事实进行快速测试。如果数据是加密的,那么您可以检查字节流中字节值的分布,您可以窃听 - 如果所有值都是均匀分布的,那么您很有可能正在处理加密文本。

为了对决定越来越有信心,您可以将测试范围扩大到更复杂的东西,例如分析字节对或三元组的分布等。

另一方面,您还可以将您感兴趣的特定语言的二元组和三元组的统计数据与您观察到的数据中出现的情况进行比较(另请参见此处)。如果您的数据表现相似,那么您更有可能观察到纯文本。

于 2011-08-09T18:26:29.603 回答
0

一种判断方法是填充。在消息末尾添加标准填充。如果解密的消息没有以标准填充结束,那么它是用错误的密钥解密的。不能保证相反,但通常是正确的。

于 2011-08-09T21:45:13.683 回答