简体中文

开发者工具 · SHA 哈希计算器

十六进制、Base64 和原始字节:编写相同 SHA 摘要的三种方法

· 工作原理

sha-256 base64 编码 文件格式

一个 32 字节摘要显示为 64 十六进制字符、44 带填充的 base64 字符、base64url 和标记字节边界的原始字节
原始 ToolAcre 矢量图

sha256sum 打印十六进制,package-lock.json 存储 base64,Docker 使用 sha256: 前缀。它们可以都是相同的 32 字节。这篇文章解释了每种表示形式以及如何在它们之间进行转换。

看起来不同但相同的哈希值 — 同一文件的锁定文件字符串和终端校验和

SHA-256 摘要本质上是 32 字节。您编写这些字节的方式决定了摘要的外观。一个摘要,32 相同字节,显示为 64 十六进制字符(每个字节两个),或 44 base64 字符(大约每三个字节四个),或者根据编码而显示不同的长度和格式。之所以会出现混乱,是因为锁文件可能显示一种表示形式,而终端显示另一种表示形式,两者都针对相同的底层 32 字节。

理解编码是转变“为什么这些看起来不同?”的步骤。变成“我可以确认它们是相同的”。一旦将它们解码回字节,所有三种表示形式都是等效的。

摘要是字节 — 20、32、48 或 64,具体取决于算法,在任何文本编码之前

在任何文本表示存在之前,结果是摘要字节的 ArrayBuffer。 ToolAcre 使用 Uint8Array 包装该缓冲区,然后将每个字节写入两个十六进制数字,或者在调用 btoa 之前将每个字节转换为二进制字符。两个格式化程序都不会重新运行哈希,也不会更改单个摘要位。

字节宽度遵循此工具中选定的算法:SHA-1 返回二十个字节,SHA-256 三十二个字节,SHA-384 四十八个字节和SHA-512 六十四个字节。这些是由算法元数据和测试验证的支持输出。原始字节适合编程比较; hex 和 base64 是需要文本的通道的传输符号。

Hex — 每个字节两个字符,为什么它在命令行工具中占主导地位,以及案例问题

十六进制表示使用数字 0-9 和字母 A-F(或 a-f)来表示 4 位半字节的 16 可能值。两个十六进制数字代表一个字节。输入 abc 的 SHA-256 摘要为 32 字节,因此它显示为 64 十六进制字符:ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad。这是大多数命令行工具打印的格式。十六进制是人类可读且明确的;每个字节每次都由完全相同的两个字符表示。

十六进制是文档和命令行中校验和和哈希的默认格式。它易于阅读和复制,并且没有填充,解释时不区分大小写(尽管约定一致规定小写或大写),并且没有需要在 URL 或 JSON 中转义的特殊字符。缺点是它需要的字符数是原始字节的两倍,这就是存在其他格式的原因。

Base64 和 base64url — 每三个字节大约四个字符、填充以及每个字符出现的位置(SRI、npm、SSH 指纹)

Base64 将三个字节编码为从 64 字符字母表中提取的四个字符:A-Z、a-z、0-9、+、/. 这三个字节 61 62 63 (ASCII 代码对于 abc) 编码为 Base64 中的 YWJj。完整的 32 字节 SHA-256 摘要编码为大约 44 base64 字符。使用 = 字符进行填充会使输出长度达到 4 的倍数,因此 44 字符加上 0 填充(因为 32 是 3 的倍数,因此不需要填充)。解码过程相反:四个 Base64 字符解码为三个字节。

Base64 出现在 package-lock.json 文件、npm Shrinkwrap、HTML 中的 SRI(子资源完整性)属性和 SSH 密钥指纹中。它很紧凑——比原始字节长大约 33%,而十六进制的长 100%。代价是并非所有文本表示都同样易于阅读。人眼看来,base64 看起来比十六进制更混乱。

前缀形式 — sha256:在容器摘要中,sha384- 在完整性属性中,SHA256:在 SSH 中

Base64url 是 RFC 4648 中定义的变体,它将 - 和 _ 替换为 + 和 /. 字母表变为 A-Z、a-z、0-9、-、_。 JWT 使用 base64url,因为 + 和 / 在 URL 中具有特殊含义(+ 可以读取为查询字符串中的空格,/ 是路径分隔符)。 JWT 段始终是 base64url 编码的,坚持使用标准 base64 的解码器将拒绝它。相反,不接受标准字母表的 Base64url 解码器将在标准 Base64 上失败。

填充在 base64url 中是可选的。标准 base64 填充 = 以确保输出长度是 4 的倍数。 Base64url 通常会省略填充,因为 = 本身就是 URL 尴尬的。解码器应该接受带有或不带有填充的 base64url,并且编码器应该明确其生成的内容。 ToolAcre base64 工具接受字母表并允许输入中缺少填充,并允许您选择输出格式。

工作示例 — 一个摘要从十六进制转换为 Base64 并返回,并标记了字节边界

前缀形式将方案标识符添加到摘要中。 Docker 镜像摘要使用 sha256:ba7816bf...,其中 sha256: 是前缀。 SSH 指纹使用 SHA256:,带有冒号。某些工具使用 sha256= 或 SHA256= (带有等号)。前缀纯粹是提供信息的;它告诉您哪个算法生成了摘要。删除前缀会在相同的编码中留下相同的字节。

比较摘要时,前缀是噪音。如果一个工具打印 SHA256:ba78... 而另一个工具打印 ba78...,则它们是相同的摘要;前缀只是有关格式的元数据。同样,像 sha256:-(在某些容器上下文中使用)或 sha384-(在完整性属性中使用)这样的前缀是不更改字节的格式约定。剥去它们进行比较。

这不包括什么——给定工具发出哪种编码;比较之前检查输出格式

一个摘要,即输入 abc 的 SHA-256,以多种形式出现:十六进制(64 字符)、带填充的 base64(44 字符)、带填充的 base64url(44 字符,用 - 和 _ 代替 + 和 /), 或使用各种前缀。确认它们是同样,将每个解码回字节并比较字节。十六进制表示 ba7816bf... 解码为字节 0xba 0x78 0x16 0xbf 0x8f 0x01 0xcf 0xea ... 解码时,base64 表示转换为相同的字节序列。

ToolAcre SHA 哈希计算器默认以十六进制输出。如果需要 Base64,可以使用单独的工具将十六进制转换为 Base64,或者使用同一站点上的 Base64 实用程序直接对文本进行编码。为特定上下文设计的工具(npm 用于 package-lock.json,Docker 用于图像摘要)以其上下文期望的格式输出。当工具在格式上不一致时,了解这些都是相同的 32 字节,可以消除混乱。

要点:比较字节,而不是字符串 - 使用 ToolAcre SHA 哈希计算器计算摘要,然后转换为您要检查的表示形式

要将十六进制摘要手动转换为 Base64,请将十六进制数字分组为字节,将每个字节转换为十进制,然后使用 Base64 字母表进行编码。字节 0xba(十六进制 ba)是十进制 186; 0x78 是 120; 0x16 是 22; 0xbf 是 191。将这四个字节分组并编码为base64,得到字符w(字母表中的0 + 22),as(编码186),AA(编码120),vw(编码191)。完整的摘要需要执行 10 次,并在需要时进行填充。这个手动过程很有启发性,但很乏味; Base64 转换器工具使其变得即时。

关键的见解是摘要首先是字节,文本表示是其次的。相同字节的每次编码都会解码回相同的字节,因此出于完整性验证的目的可以互换。十六进制的大小写差异、base64 的填充差异、前缀和间距都是不会影响实际值的格式选择。当您掌握了在表示形式之间进行转换的能力时,摘要格式不匹配就成为您可以解决的调试问题,而不是谜团。