英文文本中通常会出现哪些可打印的 ASCII 字符?

Posted

技术标签:

【中文标题】英文文本中通常会出现哪些可打印的 ASCII 字符?【英文标题】:Which printable ASCII characters will usually appear in an english text? 【发布时间】:2010-08-05 12:56:11 【问题描述】:

我已经尝试解决 Project Euler's problem #59 有一段时间了,但我遇到了麻烦,因为其中一些问题似乎比以前的问题更加模糊。

作为背景,问题表明给定的文本文件是加密文本,其中 ASCII 代码保存为数字。加密方法是循环异或3个小写字母与明文(所以它是可逆的)。该问题要求将文件解密为英文文本的密钥。我应该如何限制输出的字符集以获得答案,而不是尝试筛选所有可能的明文 (26^3)?

我尝试过限制为字母、空格和标点符号,但没有奏效。

澄清一下:我想确定,在所有可打印的 ASCII 字符中,哪些我可以丢弃,哪些我可以期望在纯文本字符串中。

【问题讨论】:

你不能指望比这更严格的定制。英文信息可能包含您提到的字母、空格和标点符号。阅读我留下的关于如何根据英文词典进一步缩小输出范围的第二条评论。如果您正确地执行此操作,则破译文本通过您的检查的几率会大大降低。如果在那之后你得到了更多,我会感到惊讶。 您的问题进展如何? 26^3 是一个很小的数字。 【参考方案1】:

您是否尝试过两种最“基本”和最常用的工具来分析所使用的算法?

    分析字符的频率并尝试将其与英文字母频率匹配 使用单词列表中的键进行暴力破解,最常见的单词被“愚蠢”用户用作键

要分析此特定问题的频率,您必须每隔三个元素拆分一次字符串,因为键的长度为 3,您现在应该能够生成三列:

79  59  12
2   79  35
8   28  20
2   3   68
...

您必须分析每列的频率,因为现在它们与键无关。

好吧,实际上我花了点时间构建了 3 个完整的列,并计算了每个列的频率,得到了两个最频繁的项目或每一列:

Col1  Col2  Col3
71    79    68
2     1     1

现在,如果您检查例如:http://en.wikipedia.org/wiki/Letter_frequency 你有最常用的字母,不要忘记你有空格和其他没有出现在该页面上的字符,但我认为你可以假设空格是最常用的字符。

所以现在只需对我提供的表格中最常见的字符进行异或运算,看看你是否得到任何小写字符,我发现了一个我认为的三个字母的单词是只有这些数据的答案。

祝你好运,顺便说一句,这是一个很好的问题!

【讨论】:

我没有想到频率分析,它可能会有所帮助,但我不确定文本是否足够长以使结果显着(它大约是一个小段落的大小)。不过,我一定会尝试的。单词表似乎是个好主意,但知道 Project Euler,他们可能选择了一个随机键。 是的,我不会指望单词列表能带你到任何地方 一个人永远不应该“不指望”任何事情,特别是当尝试从单词列表中尝试所有三个字母单词相当容易时,有一些常见的密码,如狗、上帝等。谁知道呢跨度> 相反,人们应该始终“不计较”事物。当然可以尝试将它们作为选项,但我不会将密钥存储为 3 个字母的单词。不是说你不能试试…… 谢谢。我通过频率分析得到了答案。【参考方案2】:

一种可能的解决方案是简单地假设加密文本中存在给定的三字符序列。您可以使用三个字母的单词,或可能出现在英文文本中的三个字母序列(例如" a ":两个空格之间的字母“a”)。然后简单地尝试该序列在加密文本中的所有可能位置。每个位置都允许您简单地重新计算密钥,然后将整个文本解密到一个文件中。

由于原始文本的长度为 1201,因此您需要浏览 1199 个文件。在这一点上,这只是耐心的问题,但您可以通过使用简单的文本搜索实用程序对另一个英语频繁序列(例如"are")进行更快的处理,例如使用 Unix 工具grep

我就是这么做的,不到五分钟就得到了解密的文本。

【讨论】:

【参考方案3】:

我先承认我不熟悉 XOR 密码。

但是,它似乎与 vigenere 密码的概念非常相似。特别是在他们提到不可破解加密的行中,密钥长度等于消息长度。那叫 Vernam Cipher。

如另一个答案中所述,破解维吉尼亚密码的战略方法涉及概率方法。我不会详细介绍,因为我学到的大部分理论都比较复杂,但可以找到 here 记住,vignere 是一系列凯撒密码。

这个问题对你来说很容易,因为你已经知道密钥长度。因此,正如您所提到的,您可以通过尝试每个 3 个字母组合来简单地进行暴力破解。

这就是我要做的:取一段大小合理的密文,比如 10 到 20 个字符,然后尝试暴力破解方法。跟踪所有似乎创建可理解的字母序列的密钥,然后在整个密文中使用这些密钥。这样我们就可以使用明显的暴力破解方法,但不会暴力破解整个问题,所以我认为你不必担心限制你的输出。

也就是说,我同意在您创建输出时,如果您得到一个不可打印的字符,您可能会中断循环并继续下一个键。我不会尝试比这更具体的任何事情,因为谁知道原始消息可能包含什么,永远不要对您正在处理的数据做出假设。像这样的短路逻辑总是一个好主意,尤其是在实施蛮力解决方案时。

【讨论】:

我喜欢你的想法,但它似乎仍然与我之前遇到的相同问题:我有超过 17000 个输出,我需要计算机以某种方式丢弃难以理解的输出。 在将输出限制为仅可打印的英文字符后,您有 17,000 个输出?哎呀。好的,如何从 intertubes 下载字典文件,然后在输出的前 20 个字符上使用它。因此,一旦您解密了约 15 个字符,请检查它们是否包含英文单词。更好的是,如果您不担心速度,请在每 20 个字符输出上执行子字符串,并检查开头是否是英文单词。 IE,如果第一个字母组成一个单词?不,如果前 2 个组成一个词?不,请检查前 3 个等。 对不起,看来我可能没有完全弄清楚我原来的问题。我将编辑我的问题。 主要的问题是仅仅消除不可打印字符并不足以充分缩小解决方案(大多数ascii字符都是可打印的),所以问题是确定英文中不需要哪些其他字符文本。【参考方案4】:

将密文一分为三。

Ciphertext1 包含第 1、4、7、10... 数字 Ciphertext2 包含第 2、第 5、第 8、第 11... 数字 Ciphertext3 包含第 3、6、9、12 位……数字

现在您知道每个密文都使用相同的密钥字母进行加密。现在对其进行标准频率分析。这应该会给你足够的线索来判断这封信是什么。

【讨论】:

【参考方案5】:

我几天前刚刚解决了这个问题。在不为你破坏的情况下,我想描述一下我解决这个问题的方法。我所说的某些内容可能与您已经知道的内容相比是多余的,但这是我方法的一部分。

首先我假设密钥与描述的完全一样,三个小写的 ASCII 字母。所以我开始暴力破解'aaa'并转到'zzz'。解密时,如果任何结果字节的值低于 32(空格的 ASCII 值,最低的“可打印”ASCII 值)或高于 126(波形符“~”的 ASCII 值,它是 ASCII 中最高的可打印字符) 而不是我认为密钥无效,因为 32 和 126 之外的任何值对于纯文本的英语来说都是无效字符。一旦单个字节超出此范围,我就停止解密并转到下一个可能的密钥。

一旦我使用特定密钥解密了整个消息(在通过了所有字节都是可打印字符的第一次测试之后),我需要一种方法来验证它是否是有效的解密。我期望结果是一个简单的单词列表,没有特定的顺序或含义。通过其他密码学经验,我想到了字母频率,最简单的说,你在文本中的平均英文单词是 5 个字符长。该文件包含 1201 个输入字节。所以这意味着(平均)会有 240 个单词。解密后,我计算了结果输出字符串中有多少个空格。由于 Project Euler 绝不是平均水平,因此我将空格数与 200 进行了比较,以表示更长、更晦涩的单词。当输出中包含超过 200 个空格时,我打印出用于解密的密钥和输出文本。答案是唯一一个超过 200 个空格的输出。让我告诉你,当你看到答案时,你就知道答案了。

需要指出的是,问题的答案不是关键。它是输出字符串的所有 ASCII 值的总和。这种方法也可以解决一分钟以下的方程,实际上,它的时间大约是 3 或 4 秒。

【讨论】:

以上是关于英文文本中通常会出现哪些可打印的 ASCII 字符?的主要内容,如果未能解决你的问题,请参考以下文章

ASCII码中哪些是不可打印字符

普通文本中最少使用的分隔符 < ASCII 128

iOS Base64编码

控制字符是啥

ASCII 可打印字符与控制字符

Arduino Serial.print()串口打印函数