Authentication Base64url编码表示之谜

Authentication Base64url编码表示之谜,authentication,cookies,encoding,Authentication,Cookies,Encoding,我正在编写一个cookie身份验证库,它复制了现有系统的身份验证库。我能够创建有效的身份验证令牌。然而,使用现有系统创建的具有已知值的令牌进行测试时,我遇到了以下难题 原始编码字符串声称是base64url编码的。事实上,使用几个base64url代码模块和在线工具中的任何一个,解码值就是预期结果 但是,对解码值进行base64url编码(再次使用多种工具中的任何一种)不会再现原始字符串。两个编码字符串都解码为预期结果,因此显然这两种表示都是有效的 怎么做?有什么区别 如何复制原始编码结果 原始

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

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

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

怎么做?有什么区别

如何复制原始编码结果

原始编码字符串:YWRtaW46NTVGRDZDRUE6vtRbQoEXD9O6R4MYd8ro2o6Rzrc
my base64url解码:admin:55FD6CEA:[加密哈希]

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

my base64url编码:YWRtaW46NTVGRDZDRUE677-977-9W0Lvv70XD9O6R--_vRh377-977-92o7vvv73otw
my base64url解码:admin:55FD6CEA:[加密哈希]

(很抱歉,SSE不允许我显示哈希的unicode表示形式。我向您保证,它们确实匹配。)

此字符串:

YWRtaW46NTVGRDZDRUE6vtRbQoEXD9O6R4MYd8ro2o6Rzrc
不完全有效。有效的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个可能的字节值和更多可能的字符时,尤其是考虑到中文时,这一点也开始变得更加失败

是一个不断发展的标准,它将字符映射到代码单位(即数字),目前定义的字符数略多于100000。然后一些编码规则(有几种,最常见的是UTF-8)将字符编码为字节。关键的是,一个字符可以在几个字节内编码

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

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


编辑:感谢@marfarma指出“+”和“/”字符替换为“-”和“"”的位置。这使情况更加清楚。添加所需的“=”符号时,第一个字符串将解码为:

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                                                |.|
我们现在看到发生了什么:第一个字符串被解码为字节,但有人将这些字节提供给一些真正需要UTF-8的显示系统或编辑器。其中一些字节不是有效的UTF-8编码,因此它们被替换为Unicode代码点U+FEFF零宽度无中断空格,即没有宽度的空格字符(因此,屏幕上为空)。然后重新编码为UTF-8的字符,每个U+FEFF产生三个字节的EF BF BD序列

因此,散列值被严重损坏,但被更改的字节在被(错误地)解释为字符时显示为空,而放在其位置上的内容也显示为空。因此,屏幕上没有明显的差异。

此字符串:

YWRtaW46NTVGRDZDRUE6vtRbQoEXD9O6R4MYd8ro2o6Rzrc
不完全有效。有效的Base64由大写字母、小写字母、数字“/”和“+”之间的字符序列组成;其长度也必须是4的倍数;1或2个最后的“=”符号可能显示为填充符号,因此长度实际上是4的倍数。此字符串仅包含Base64有效字符,但仅包含其中47个,47不是4的倍数。如果在末尾有一个额外的“=”符号,则此值变为有效的Base64

该字符串:

YWRtaW46NTVGRDZDRUE677-977-9W0Lvv70XD9O6R--_vRh377-977-92o7vv73Otw
是无效的Base64。它包含几个“-”和一个“-”符号,这两个符号都不应出现在Base64字符串中。如果某个工具正在将该字符串解码为与前一个字符串“相同”的结果,那么该工具根本就没有实现Base64,而是实现了其他东西(而且很奇怪)


我想您的字符串在某种程度上由于复制和粘贴错误而变得混乱,可能与字节作为字符的错误解释有关。这一点很重要:字节不是字符

碰巧的是,传统上,在旧时代,计算机习惯于使用所谓的“代码页”,即直接映射