编码链解码器

被不止一种编码器处理过的文本才是常态,而不是特例:Base64 令牌里嵌着 JSON 正文、日志行里嵌着 URL、表单值先被百分号编码又被 Base64 编码以便放进请求头。本页一层一层解开这些编码,标出每一步用到的技术、打印它的置信度和理由,并列出它在每一步否决了哪些技术,让你可以不同意它的判断。当文本不再像被编码过、达到步数上限、或下一步会带回已经见过的文本时停止。没有任何静默猜测:字母表与普通单词重叠的技术永远不会被自动应用,只会被列出。
所有处理都在浏览器本地进行——你的数据绝不上传到任何服务器。

初次接触?用平实的语言解释编码链——什么是层、为什么编码不是加密、以及为什么步骤的顺序很重要。
只有置信度不低于以下值时才自动应用一层:
最多解开
一次性执行上面的层数上限。两种方式生成的是同一张表,所以你可以在任何时刻切换为手动步进。
或者手动挑选一项技术:
这个列表是页面此刻在文本中能看到的东西。旋转密码始终在列表里,因为它们根本无法被检测;还有那些只有去掉换行排版才变得可识别的条目——它们会被明确标注,且永远不会被自动应用。
这段输入的长度超出了本页不询问就运行的范围,上面的估计显示可能需要 。再点一次解开整条链表示继续,或者先缩短文本。
(先输入或粘贴一些内容)
(链将显示在这里)
什么是编码链,为什么它需要专门的解码器?

一个层就是套在文本上的一种编码。链是两层或更多层依次叠加。几乎每个日常案例都是这样产生的:有人需要把一段二进制——一张图片、一个签名令牌——放进只能承载文本的地方,于是做了 Base64。Base64 的结果要放进 URL,于是又被百分号编码。整个 URL 又要写进日志行或配置文件,于是反斜杠或引号也被转义。你遇到问题时看到的只是最外层,它之所以不可读,原因很简单:里面的层还没解开。

单一用途的解码器对此无能为力。把 JTI2bHQlM0JiJTI2Z3QlM0JoaSUyNmx0JTNCJTJGYiUyNmd0JTNC 交给 Base64 解码器,会得到一个完全正确但依然不可读的答案,因为百分号转义和字符引用还压在你想要的文本之上。你真正需要的是在每一步决定该解开哪种编码器的东西——本页就是把这道决策过程展示出来。

编码不是加密,本页不破解任何东西。本页上的每种技术都是把同样的信息写下来的公开、可逆的方式。Base64 没有密钥。百分号转义没有密钥。如果最内层是加密的,本页会解开外层并交给你密文,并且会明说出来,而不是假装那是结果。这里没有任何可运行的东西,也没有任何可隐藏的东西。
本页的实例演示

下面每一行都是本页数据文件里的真实输入,中间一列是本页自己的解开器在其中的发现。最后一列是它停下来时剩下的文本。

输入是什么 发现的层 输入(原样引用) 停止时剩下

这些行由本页根据自己的案例列表渲染,并在每次访问时重新运行,因此它们不可能偏离代码的实际行为。下面的自测会逐条检查。

本页如何决定解开哪一层
  1. 看形状,不看含义。每种技术都有一个签名——一个百分号转义、一段等长的十六进制、一个匹配 Base64 的字母表和长度。本页列出签名匹配文本的每一种技术,并给出 0 到 1 之间的置信度。
  2. 先解码,再看结果是不是文本。只有能产生可读结果的技术才值得应用。每个候选都会真的运行一遍,其输出按可打印字符的占比打分。
  3. 只应用过线的,按置信度排序。置信度最高且高于你阈值的候选会被应用,然后在结果上重复这一过程。低于阈值的只列出、不应用。
  4. 本页在此基础上增加的一条规则。即使某项技术过了阈值,本页也不会自动应用它,除非结果确实是可读文本——替换字符和控制字符会被扣分。没有这条规则,普通单词 cafe 会被“合法地”解码成三个只在 Latin-1 下可打印的字节,getUserName 会被解码成八个字节的噪音。检测器没算错——那些字符串确实符合字母表;但本页认为符合字母表并不够。你仍然可以手动应用它们,候选列表会告诉你它拒绝的原因。
  5. 有节制地停止。当没有技术过线、文本不再变化、达到步数上限、或下一步会带回链中已经出现过的文本时停止。最后一条很重要:ROT13 是自己的逆变换,允许重复该步骤的链永远不会结束。
  6. 换行排版只提供,不自动应用。如果文本被切成多行,检测器看到的是空白,读到的是普通散文,什么都找不到。于是本页把一份文本副本中的空白去掉,再次询问检测器,并把找到的东西作为手动选择的步骤列出。从文本中去除空白是对文本的改写,而本页不会改写任何你没有要求改写的东西。
本页不会做的事
它只解码,别的什么都不做。你粘贴的文本从不被执行:没有 eval、没有 new Function、没有脚本注入、不打开文档。它也从不被发送到任何地方:没有上传、没有请求、没有统计。除了页面底部的广告位和分享按钮行(那是本页加载的仅有的两个第三方组件),不从其他主机获取任何字体或脚本。解码输出以文本形式写入页面,因此某一层解出来的 HTML 标签会被显示为文字,而不是变成真的标签。你可以验证这一切:按自测,它会检查本页自己的源码中是否含有这些构造,发现即失败。
它能识别什么,不能识别什么
技术 单独使用时的把握 陷阱

本页引用的文本是为本站编写的。Base64、Base32、Base58、Base91 和 quoted-printable 的字母表以及 uuencode 的块格式都是公开发布的定义;解码遵循这些定义而不是任何特定工具的怪癖。各字母表的参考向量在姊妹页面上,那里带有 RFC 4648 测试向量。

以多行排版到达的文本

经过电子邮件、PEM 文件、请求头里的令牌或从终端粘贴出的哈希的数据块通常是折行的:编码器在固定列宽处断行——76 个字符是 MIME 惯例——并在列末放一个换行。这些换行不是数据的一部分。它们的存在是为了让长行能在传输中存活,每个读取这种数据块的解码器都被期望忽略它们。

本页不会自动忽略它们,理由就是它在其他地方使用的同一条规则。空白是“一串字符是散文而不是数据”的最强信号,正是这个测试让 The quick brown fox jumps over the lazy dog. 不会被读成任何东西。折行的数据块在那个测试看来与散文一模一样,所以本页在它里面什么也找不到——然后做诚实的那一半工作:算出如果去掉空白它会发现什么,把手动选择器中标为先去空白的条目列出来,然后停在那里。之所以只列出而不应用,是因为去除空白会改动你的文本,而本页只在能证明改动内容时才改动文本。这里它能证明改动是什么,却仍然拒绝替你做,因为值中间有换行的文本和两个字段之间有换行的文本,从内部看起来一模一样。

页面在折行文本上停下时的两步操作。切换到手动一步步进行,按一次应用下一层(这让页面有一条可以追加的链,它什么也不改变),然后选中标记为先去空白的条目并按应用。随之产生的那一行会说明去掉了多少个空白字符,并把它的输入大小记为你粘贴的文本,因此该行两个数字之差正好是去掉的空白量。

同样的推理也覆盖方向相反的情况。uuencode 块带有 begin 行和每行的长度字符,因此它本身就可识别并会被自动应用;quoted-printable 正文保留自己的软换行,由它自己的解码器解码,该解码器知道行尾单个的 = 是续行而不是数据。当形状测试无法区分散文与数据时,本页选择拒绝并向你展示备选项,而不是替你做决定。

本页会运行什么,拒绝运行什么

下表由本页强制执行的同一组常量构建,因此本页的表格与警告不可能互相矛盾。让人意外的两行是 Base58 和 Base62:这两种技术用长除法转换,其开销随长度的平方增长,所以本页只对短字符串运行它们,并在步骤里说明,而不是假装卡死。

这些估计是刻意悲观的。它们来自计时基准而不是你的机器,桌面浏览器通常比所示数字快好几倍。