Base64url编码表示拼图

时间:2015-09-21 16:35:20

标签: authentication cookies encoding

我正在编写一个复制现有系统的cookie身份验证库。我能够创建有效的身份验证令牌。但是,使用现有系统创建的具有已知值的令牌进行测试时,我遇到了以下难题。

原始编码字符串声称是base64url编码的。事实上,使用几个base64url代码模块和在线工具中的任何一个,解码后的值就是预期的结果。

然而,对解码值进行编码的base64url(再次使用几种工具中的任何一种)都不会重现原始字符串。两个编码的字符串都解码到预期的结果,因此显然两种表示都是有效的。

如何?有什么区别?

如何复制原始编码结果?

original encoded string: YWRtaW46NTVGRDZDRUE6vtRbQoEXD9O6R4MYd8ro2o6Rzrc my base64url decode: admin:55FD6CEA:[encrypted hash]

编码与原始编码不匹配,但解码后的字符串匹配。

my base64url encode: YWRtaW46NTVGRDZDRUE677-977-9W0Lvv70XD9O6R--_vRh377-977-92o7vv73Otw my base64url decode: admin:55FD6CEA:[encrypted hash]

(对不起,SSE不会让我显示哈希的unicode表示。我向你保证,他们确实匹配。)

1 个答案:

答案 0 :(得分:3)

此字符串:

YWRtaW46NTVGRDZDRUE6vtRbQoEXD9O6R4MYd8ro2o6Rzrc

不是完全有效Base64。有效的Base64包含大写字母,小写字母,数字,'/'和'+'之间的字符序列;它的长度也必须是4的倍数; 1或2个最终'='符号可能显示为填充,因此长度确实是4的倍数。此字符串仅包含Base64有效字符,但只有47个,而47不是4的倍数。最后的'='符号,这将成为有效的Base64。

那个字符串:

YWRtaW46NTVGRDZDRUE677-977-9W0Lvv70XD9O6R--_vRh377-977-92o7vv73Otw

无效Base64。它包含几个' - '和一个'_'符号,它们都不应出现在Base64字符串中。如果某个工具将该字符串解码为与前一个字符串“相同”的结果,那么该工具根本不会实现Base64,而是其他东西(并且很奇怪)。

我认为你的字符串在某些时候通过一些复制和粘贴事故而变得混乱,可能与字节作为字符的错误解释有关。这一点很重要:字节不是字符

传统上,在旧时代,计算机养成了使用所谓的“代码页”的习惯,这些代码页是将字符直接映射到字节上,每个字符被编码为一个字节。因此产生了一些声称做反向的工具(例如Windows'notepad.exe),即显示文件的内容(名义上,一些字节),因为它们对应于对应物。但是,当字节不是“可打印字符”时,这会失败(当“Windows-1252”等代码页将每个字符映射到一个字节值时,可能存在不是可打印字符映射的字节值)。当人们最终意识到只有256个可能的字节值,以及更多可能的字符时,尤其是在考虑中文时,这也开始失败了。

Unicode是一种不断发展的标准,它将字符映射到代码单元(即数字),当前定义的位数超过100000。然后一些编码规则(其中有几个,最常见的是UTF-8)将字符编码为字节。至关重要的是,一个字符可以在几个字节上进行编码。

在任何情况下,哈希值(或任何你称之为“加密哈希”,这可能是一个混乱,因为哈希和加密是两个不同的东西)是字节的序列,而不是字符,因此永远不能保证是任何代码页中字符序列的编码。

有了这些知识,你可以尝试在你的字符串和问题中加入一些顺序。

编辑:感谢@marfarma指出URL-safe Base64 encoding,其中'+'和'/'字符被' - '和'_'替换。这使情况更加清晰。添加所需的'='符号时,第一个字符串会解码为:

00000000  61 64 6d 69 6e 3a 35 35  46 44 36 43 45 41 3a be  |admin:55FD6CEA:.|
00000010  d4 5b 42 81 17 0f d3 ba  47 83 18 77 ca e8 da 8e  |.[B.....G..w....|
00000020  91 ce b7                                          |...|

而第二个变为:

00000000  61 64 6d 69 6e 3a 35 35  46 44 36 43 45 41 3a ef  |admin:55FD6CEA:.|
00000010  bf bd ef bf bd 5b 42 ef  bf bd 17 0f d3 ba 47 ef  |.....[B.......G.|
00000020  bf bd 18 77 ef bf bd ef  bf bd da 8e ef bf bd ce  |...w............|
00000030  b7                                                |.|

我们现在看到发生了什么:第一个字符串被解码为 bytes ,但有人将这些字节输入到某些真正期望UTF-8的显示系统或编辑器。这些字节中的一些不是任何东西的有效UTF-8编码,因此它们被替换为Unicode代码点U + FEFF ZERO WIDTH NO-BREAK SPACE,即没有宽度的空格字符(因此,屏幕上的虚无)。然后重新编码为UTF-8的字符,每个U + FEFF产生三个字节的EF BF BD序列。

因此,哈希值被严重破坏,但是当被解释(错误地)为字符时,被改变的字节显示为什么,并且放在它们的位置也显示为什么都没有。因此在屏幕上没有明显的差异。