简体中文

开发者工具 · Base64 编码器和解码器

Base64 vs hex vs base32:比较将字节写入文本的三种方法

· 背景

base64 编码

相同 16 字节的 Base64、十六进制和 Base32 密度和可读性比较
原始 ToolAcre 矢量图

He​​x、base32 和 Base64 解决了相同的问题,但在大小、可读性和安全性方面有不同的权衡。这篇文章对它们的密度、区分大小写、URL 安全性和人为错误进行了比较。

由于 l、1、I 和 O 而输入错误的 API 密钥 — 这是十六进制不会出现的具体可读性故障

将字节表示为文本的三种常见方法是十六进制、base32 和 base64。它们都解决相同的问题(以可打印 ASCII 表示任意字节),但在大小、可读性和错误恢复能力方面有不同的权衡。十六进制为每字节 2 个字符 (F3 A2 B1 ...),因此 16 字节变为 32 个字符。 Base32 为每字节 1.6 个字符(每 3 字节大约 5 个字符),因此 16 字节变为 26 个字符。

Base64 为每字节 1.33 个字符(每 3 字节恰好 4 个字符),因此 16 字节变为 24 个字符或更少。如果文件大小很重要,base64 是最紧凑的。如果人类转录很重要,则 hex 和 base32 更安全。当输入、复制或说出值时,可读性差异至关重要。 Hex 使用 0-9 和 a-f (在大多数情况下不区分大小写)。转录通道改变了决定,因为针对机器优化的表示对于人们来说可能会很尴尬。 Base64 区分大小写并使用两个标点符号; hex 使用较小的视觉词汇。这里的实现测试的是精确的字符串,而不是人为错误率,因此没有附加发明的概率。

密度:2×、1.6× 和 1.33× — 每种编码每个字节需要多少个字符以及原因

Base32 使用 A-Z 和 2-7,避免纸上容易混淆的 0、1、O 和 I。 Base64 使用 A-Z、a-z、0-9、+ 和 /,(包括大写和小写),使其区分大小写并混合看起来相似的数字(0 与 O、1 与 I 与小写 l)。十六进制的 API 密钥可能是 f3a2b1e4; base64 中的相同字节可能是 86KrvE== (带填充),或者在 base32 中 6VEV7FI= (带填充)。

如果用户必须手动输入值,则十六进制或 Base32 比 Base64 更安全。 URL 中的保留字符很重要。 Hex 和 base32 对于 URL 来说是安全的;两者都仅使用字母数字字符(十六进制也使用 0-9,base32 也使用 2-7)。 Base64 使用 URL 保留的加号和斜杠(加号表示表单编码数据中的空格,斜杠是路径分隔符)。 Base64 密度直接来自每个输出符号的六个有用位和四个字符块的填充。十六进制每个符号携带四位,即每个字节两个字符。 Base32 仅作为比较上下文进行讨论,因为该存储库既不提供其字母表也不提供编码器来验证输出。

位宽密度 — 精确的 Base64 和十六进制算术,将 Base32 视为比较上下文

URL 参数中的 base64 字符串必须进行百分比编码(加号变为 %2B,斜杠变为 %2F),为每次出现添加 4 额外字符。 Base64url(RFC 4648 部分 5)将加号替换为破折号,将斜杠替换为下划线,从而使其无需百分比编码即可实现 URL 安全。大多数在 URL 中使用 base64 的 API 实际上都使用 base64url,但文档中的区别通常并不明确。

TOTP 机密(身份验证器应用程序使用的代码)通常以 base32 形式分发。 TOTP 注册屏幕显示 Base32 密钥,因为它比 Base64 或十六进制的相同字节更容易键入和转录。 SHA 哈希摘要通常以十六进制显示,因为它是传统格式,而且十六进制不区分大小写,因此不太可能出现拼写错误。当有人大声读出一个值或重新输入它时,区分大小写很重要,因为更改一个字母的大小写会更改其索引。 ToolAcre 准确地保留大小写,并在不知道人类犯了转录错误的情况下解码生成的不同字节。该表示本身没有校验和。

保留字符和 URL 安全 — + 和 / 咬合的位置,以及 base32 和 hex 如何避免该问题

JWT 使用 base64url。文件校验和可能是十六进制或base64;两者都很常见。这种选择是历史惯例,而不是技术上的必然。错误恢复能力是一个微妙但重要的区别。 Base32 避免使用数字 0、1、8 和 9(看起来像字母),从而减少转录错误。 Base64 包含所有数字,使得 1 不明确(是字母 I、小写 l 还是数字 1?)。

十六进制更容易出错:0 看起来像 O,l 看起来像 1。必须键入或从打印输出中读取的校验和在 base32 中更安全。直接从计算机粘贴的 API 密钥在任何格式下都是安全的;仅当涉及人眼时,可读性才重要。字节相同,但编码不同:16 字节序列 [0xf3, 0xa2, 0xb1, ...] 变为 f3a2b1... 标准 Base64 的加号和斜杠需要通道感知处理; URL 安全模式将它们替换为连字符和下划线。十六进制通过单独使用数字和字母来避免这些分隔符。 Base32 约定各不相同,因此本文避免了存储库未实现或测试的有希望的安全属性。

工作示例:所有三种编码中的相同 16 字节 — 长度比较和目视检查

(十六进制)、6VEV7FI=...(base32)和 86KrvE==(base64)。这些字符串都不可互换。接收 f3a2b1... 的应用程序需要十六进制并尝试将其解析为十六进制。如果应用程序需要十六进制,则接收 86KrvE== 将失败。编码格式是数据合同的一部分:发送者和接收者必须就使用哪种编码达成一致。填充是另一个区别。

He​​x 不使用填充(4 字节始终是 8 十六进制字符,没有例外)。 Base32 和 Base64 都使用 equals 填充将输出对齐到多个字符(对于 Base32 为 8,对于 Base64 为 4)。填充在数学上是必要的;它确保每个 n 字节输入产生确定的字符计数。填充规则各不相同:一些应用程序需要填充,其他应用程序允许省略填充。工作比较使用固定字节序列并机械计算 Base64 和十六进制。它的 Base32 长度可以从五位分组来讨论,但省略了精确的 Base32 文本值,因为没有经过审查的实现生成它。长度算术和输出验证保持不同。

其中每个都是常规的 — 十六进制哈希值、base32 格式的 TOTP 秘密、JWT 和数据:Base64 格式的 URI

当粘贴不带填充的 Base32 或 Base64 值时,解码器可能会接受或拒绝它,具体取决于实现。加密密钥和令牌显示编码差异。

HMAC 密钥为 32 字节,它变为 64 十六进制字符、52 base32 字符(带填充)或 44 base64 字符(带填充)。分发密钥时,应记录编码。如果文档说密钥是 44 base64 字符,但您收到 52 字符,则说明有问题。惯例可以指导读者,但并不能证明适用性。哈希摘要通常显示为十六进制,而 JWT 段使用 Base64url。正确的选择仍然取决于通道规则、人们是否复制该值以及另一个协议是否已经修复了表示。

这不包括什么——base58、base85 和校验和编码

较短的 base64 编码使得将令牌更容易地适应有字符限制的系统(例如 QR 代码或 URL)。值的编码选择是由它来自的生态系统决定的。 Web API 通常使用 base64url。加密文档通常使用十六进制。身份验证器应用程序使用 base32。构建系统时,选择一种编码,清楚地记录它,并坚持使用。

混合编码(例如 base64 或 base32)会带来混乱。调试时,第一步是识别该值使用哪种编码; Base64 编码器和解码器工具可以通过尝试多种方式对其进行解码并查看哪种方式产生合理的输出来提供帮助。没有一种编码是普遍更好的。 Base64 对于原始存储来说是最紧凑的。十六进制对于密码学家来说是最熟悉的,对于小序列来说也是最容易被人类阅读的。 Base58、Base85 和校验和编码进行了不同的权衡,并且在 ToolAcre 的 Base64 面板中不存在。它们的字母表、歧义规则和校验和应该使用专用的来源和实现来评估,而不是从该工具的测试行为中推断出来。

要点:选择通道和阅读器的编码 — Base64 编码器和解码器如何覆盖浏览器中的 Base64 情况,以及同一产品中的 SHA 哈希计算器

Base32 对转录错误的恢复能力最强。选择取决于上下文:价值存在于何处、如何共享以及哪些系统将使用它。

了解权衡有助于您在设计 API 或系统时做出明智的选择。 Base64编码器和解码器工具演示了base64编码;将其与十六进制或 base32 工具一起使用可以让您看到所有三种格式的相同字节并了解它们的大小和可读性差异。对于 Base64 情况,对示例进行编码,记下确切的 UTF-8 字节和输出字符计数,并测试标准标点符号与 URL 安全标点符号。对于摘要工作,请使用单独的 SHA 面板。保持这些操作不同可以防止编码选择被误认为是散列或完整性保护。