开发者工具 · Base64 编码器和解码器
Base64 与 base64url:为什么标准解码器拒绝 - 和 _
· 工作原理
base64 编码 开发人员工作流程
base64url 将 + 和 / 交换为 - 和 _,因此输出可以在 URL 和文件名中传输而无需转义。这篇文章解释了这两个字母、如何在它们之间进行转换以及为什么通常也会删除填充。
该令牌可在除您的代码之外的所有位置进行解码 — 由单个 - 或 _ 引起的无效字符错误
JWT 段无法在标准 Base64 解码器中解码,并出现无效字符错误命名破折号。但从视觉上看,没有出现破折号。再看看——确实如此。 base64url 版本使用 - 其中标准 Base64 使用 +,而 _ 使用 /. 许多解码器仅接受一种字母表,并且为 URL 安全编码的令牌将被期望 RFC 4648 标准 Base64 的代码拒绝。
这两个字母是等效的;它们之间的转换是机械的字符替换。出现问题的原因是 + 和 / 在 URL 中具有含义。加号表示 application/x-www-form-urlencoded 表单数据中的空格。正斜杠是 URL 中的路径分隔符。如果您将 Base64 直接嵌入到 URL 查询参数中而不进行百分比编码 + 和 /, 解码器可能会误解它们。
为什么 + 和 / 是 URL 和文件名中的问题 — / 在路径中的保留含义以及 + 在表单数据中作为空格的保留含义
A + 在到达解码器之前可以被读取为空格。 / 可能会在错误的位置分割参数值。 RFC 4648 部分 5 定义了 base64url 字母表以消除歧义:使用 - 代替 +,使用 _ 代替 /,,因此 URL 和文件名中的输出是安全的。除了两个字符之外,这两个字母是相同的。
标准 Base64 在位置 62 和 63 使用字符:A–Z (0–25)、a–z (26–51)、0–9 (52–61), + (62), / (63)。 base64url 使用 A–Z (0–25)、a–z (26–51)、0–9 (52–61)、- (62),_(63)。其他一切——位重组、填充规则、将位映射到索引——都是相同的。标准 Base64 的索引字符串将生成 Base64url 的索引字符串;只有位置 62 和 63 处的字符会有所不同。
RFC 4648 部分 5 中的 base64url 字母表 — 两个替换字符以及为什么没有其他变化
如果输入不包含索引 62 或 63 (标准中没有 + 或 /,base64url 中没有 - 或 _),则两个字母表会产生相同的输出。将标准 Base64 转换为 base64url 是简单的查找和替换:将 + 替换为 - 并将 / 替换为 _。解码标准 Base64 中的 base64url 字符串需要反向:交换 - 为 + 和 _ 为 /.
转换是对称的并且始终有效。如果您遇到令牌解码失败并出现无效字符错误命名 - 或 _,请检查解码器是否接受 base64url。如果不是,则应用字符替换,如果输入格式正确,则解码应该成功。考虑 JWT 标头 {"alg":"HS256","typ":"JWT"} 编码为 base64url。标准 UTF-8 字节经过位重组:三个字节变成四个索引,在 base64url 字母表中查找。 ToolAcre 将填充公开为编码器选择,而不是将其绑定到字母切换。这种分离是有用的证据:URL 安全输出可以被填充或不填充,而解码器在调用浏览器原语之前规范化任一形式。字母和填充是相关的约定,而不是一个开关。
填充是可选的 — 为什么 JWT 省略 = 以及解码器如何从长度恢复它
当索引为 62 时,输出字符为 -;当 63 时,输出为 _。标准字母表中的相同字节将在索引 62 处生成 +,在索引 63 处生成 /。将 base64url 结果转换为标准是逐字符操作:扫描 - 并替换为 +,扫描 _ 并替换为 /,,然后照常解码。
您恢复的字节是相同的,因为索引是相同的;只是符号不同。按照惯例,base64url 中的填充是可选的,即使标准允许这样做。 JWT 的结构为三个由点连接的 base64url 段;如果需要,每个段都会使用填充,但许多实现会忽略它并依赖于消费应用程序知道预期字节长度的事实。
工作示例:将 JWT 标头段转换为标准 Base64 — 替换字符、添加填充、解码为 JSON
解码器可以通过将字符串长度除以四、计算余数、附加 0、1 或 2 等号来恢复丢失的填充。如果字符串长度不是四的倍数,则明显缺少填充。如果长度是四的倍数,则字符串要么被填充,然后删除填充,要么输入已经是四个字节的倍数(在最终块中以三个字节结束,不需要填充)。
连接 base64url 段需要注意填充。如果三个段均以 = 结尾,则连接直接生成类似 AAAA=BBBB=CCCC= 的字符串,其中中间的填充现在是杂散字符,而不是终止标记。这就是 JWT 在每个段中省略填充的原因:三段结构是显式的,因此解码在每个部分上独立进行,并且连接字符串中间的填充是不必要的,并且会破坏解析。
常见错误 - 在一个字符串中混合字母,或使用百分比编码标准 Base64 而不是使用 base64url
如果构建多段有效负载,请在开始时决定填充约定:要么包含在每个段中并且从不直接连接,要么省略并仅在解码时从长度恢复。 RFC 4648 标准是这两种字母表的权威。 4 节指定标准 Base64; 5 部分指定 base64url。每个合格的解码器都应该清楚地说明它接受哪个字母表。
接受 base64url 但不接受标准 Base64(反之亦然)的代码仅实现子集。 base64url 字母表的存在是为了与 URL 和文件名约束兼容;它不是改进或替代,只是特定环境的变体。当您编写 API 或令牌格式时,请选择一种字母表并记录哪一种。一个常见的错误是使用百分比编码标准 Base64 而不是使用 base64url。该实现还解释了文章边界。它在解码之前标准化连字符和下划线,但它不验证令牌签名或解释声明。将 JWT 段转换为字节可以显示 JSON;它无法确定是谁发布了 JSON 或是否有人更改了它。
这不包括什么 - 验证 JWT 签名、base32 和其他 RFC 4648 编码
%2B 是 + 的百分号代码; %2F 是 /. 的百分比代码 百分比编码将 TWFu 转换为 TWFu 不变(无特殊字符),但 TE9S+g== 转换为 TE9S%2Bg%3D%3D(字符太多,无法处理)。正确的解决方案是使用 base64url,它已经生成 URL 安全的输出。百分比编码 Base64 是多余且浪费的。使用正确的字母表作为上下文。 Base64 编码器和解码器自动接受这两种字母。
如果粘贴包含 - 的字符串,它会将其视为 base64url;如果粘贴包含 + 的字符串,则将其视为标准 Base64。工具还接受 URL 并将其视为 URL 安全输入。因此,实际检查有两个独立的结果:字节往返,以及所选表示适合其通道。通过第一个表示转变是可逆的。通过第二个表示标点符号和填充不会被承载它的 URL、文件名、cookie 或协议重写。
要点:两个字母表,一位布局 — Base64 编码器和解码器如何处理浏览器中的标准字母表,以及其工具页面在何处说明它接受的内容
解码 JWT 段或 URL 安全令牌时,无需转换即可直接粘贴,工具从上下文中识别字母。调试失败的解码变得简单:粘贴令牌,查看工具是否接受它,如果不接受,则手动交换字符并重试。
替换本身是一行代码,但失败的解码也可能来自不可能的长度、错误的填充、损坏或非 Base64 输入。该工具会自动标准化两个字母表,因此接受仅确认可以恢复字节。解码后的 JWT 有效负载仍然是未签名的声明,直到单独的验证者检查其签名和预期算法为止。