开发者工具 · SHA 哈希计算器
内容寻址:Git、Docker 和 npm 如何使用 SHA 摘要作为名称
· 背景
sha-256 码头工人 密码学 开发人员工作流程
Git 提交、容器镜像摘要和锁文件完整性字符串都是相同的想法:通过哈希值命名数据。这篇文章解释了内容寻址以及每个生态系统从中获得的收益。
sha256:在你的 docker pull 中 - 该字符串是什么以及为什么它对于同一图像永远不会改变
版本控制系统、容器运行时和包管理器都使用相同的命名思想:文件或字节集合由其 SHA 摘要命名。在 Git 中,提交的 40 字符 SHA-1 标识符(或现代存储库中的 64 字符 SHA-256)是根据提交的内容(树、作者、时间戳和消息)计算得出的。更改单个字节,SHA 就会更改。在 Docker 中,每个层摘要都是该层内容的 SHA-256 哈希,并且图像摘要是根据清单计算的。在 npm 和其他包管理器中,完整性字段存储 tarball 的 SHA-512 摘要以验证下载。内容寻址意味着名称仅取决于字节,而不取决于中央数据库或时间戳。
好处是每个系统内的不变性。 git commit SHA-256:abc... 将始终引用相同的树和消息,因为哈希决定了身份。如果有人声称使用相同的 SHA 进行了不同的提交,那么他们就声称相同的字节会产生两个不同的哈希值,这会破坏密码学。重复数据删除变得自动:两个具有相同字节的文件产生相同的摘要,因此存储系统可以存储字节一次并引用它们两次。完整性检查变得像重新计算摘要并进行比较一样简单:如果字节在传输或静止时被修改,则摘要不再匹配。
通过哈希值命名数据 — 内容寻址思想以及为什么它可以实现重复数据删除和完整性自由
Git 存储对象(提交、树、blob 和标签),并通过 SHA 摘要进行键入。 `git cat-file` 命令采用对象 ID 并检索字节。对象存储是内容寻址的:您通过摘要请求,而不是通过位置或名称。当您克隆存储库时,git 通过重新计算其摘要并检查传输中打包的摘要来验证每个对象。从 SHA-1 到 SHA-256 的过渡是渐进的;存储库可以支持两者以实现兼容性。磁盘格式存储对象类型、大小和压缩字节。摘要是根据规范的未压缩形式计算的。
现代 Git 存储库可以使用 SHA-256,并且转换正在进行中,因为 SHA-1 冲突现在已经实用(在 2017 中演示并在 2020 中改进)。使用 SHA-256 的存储库中的提交具有 64 字符十六进制标识符,而不是 40。 `git hash-object` 命令计算 blob(文件内容)的 SHA,而不存储它; `git commit-tree` 计算树结构和消息的 SHA。两种操作都是确定性的:相同的字节总是产生相同的摘要。这就是 GitHub 和其他伪造者如何一致地显示提交 SHA 的方式——它们计算出与作者的克隆计算出的相同的摘要。
Git 使用内容寻址对象,该工具可以重现文本摘要;迁移详细信息需要特定于 Git 的源
Docker 镜像是分层构建的,其中每一层都是一个文件系统增量(相对于上一层的更改)。 OCI 图像规范定义了如何计算层的摘要和图像清单的摘要。层摘要是包含层文件的压缩 tar 文件的 SHA-256。清单是一个 JSON 文档,列出了各层、它们的摘要和元数据。图像摘要是清单 JSON 本身的 SHA-256 。当您使用 `latest` 之类的标签拉取映像时,注册表会查找该标签并返回清单摘要。然后,您可以直接提取摘要,确保每次都获得完全相同的字节(所有层和元数据)。
本地映像上的 `docker inspect` 命令显示其摘要。如果注册表仍然保留指向相同清单的标记,则在两台计算机上运行相同标记的相同图像会产生相同的摘要。内容寻址使图像供应链可审计:CI/CD管道可以验证其部署的图像是否与构建日志中的摘要相匹配,并且安全扫描器可以通过其摘要而不是通过可以移动的标签来报告已知具有特定漏洞的所有图像。
容器 — OCI 清单和层摘要,以及为什么标签可以移动但摘要不能移动
包管理器使用摘要来验证下载是否被篡改或损坏。在 npm 中, `package-lock.json` 文件包含每个依赖项的 `integrity` 字段,其中包含哈希(通常为 SHA-512)和编码(通常为 base64)。当 npm 下载 tarball 时,它会重新计算哈希值并进行比较。如果哈希值不匹配,则安装失败。 Go 使用具有类似结构的 `go.sum` 文件:模块路径、版本和模块源的 SHA-256 。 Cargo 在 `Cargo.lock` 中使用校验和。原理是相同的:在首次解析依赖项时计算一次摘要,并在每次后续安装时进行检查。
完整性检查不需要将包上传到签名机构或单独存储签名。摘要是完整性检查。为了获得最大程度的保证,项目使用由 Go 项目的透明系统签名的 `go.sum` ,或 npm 完整性与其他验证相结合,但基本情况很简单:发布者计算一次摘要,将其记录在锁定文件中,消费者端的工具验证下载的字节是否匹配。
包完整性编码有所不同;此处仅断言此计算器支持的 SHA 输出
通过相同算法的相同字节始终产生相同的摘要,无论字节来自何处。开发人员的本地提交生成与 CI/CD 系统从同一存储库检出相同修订版相同的 SHA-256 。这种可重复性就是内容寻址起作用的原因:您可以在不信任交付机制的情况下验证工件。摘要成为一种加密承诺:即使更改一个字节也会使其失效。
单独分发摘要(在分发工件之前)可以防止进行中的修改。发布前发布的网页可以显示“expect SHA-256:abc...”,然后用户可以根据它验证下载。在公共存储库中发布的 git 提交是对字节的承诺;摘要证明了这一点。
工作示例 — 遵循一个从要摘要的字节到工具使用的名称的 blob
不同的系统对其摘要进行不同的编码。 Git 默认使用小写十六进制(40 或 64 十六进制字符)。 Docker 使用格式 `sha256:` 后跟十六进制。 npm 和 Go 在完整性字段中使用 base64。字节相同;只是表示方式不同。 “abc”上的 SHA-256 摘要始终是相同的 256 位,但您可能会将其视为 64 字符十六进制字符串、44 字符 base64 字符串或类似 `sha256:` 之类的标签,后跟其中之一。编码之间的转换是无损的;每个表示中的摘要都是相同的值。
在比较不同工具的摘要时,了解编码很重要。如果 Git 打印十六进制摘要并且工具显示 base64,则必须将一种表示形式转换为另一种表示形式以验证它们是否匹配。 ToolAcre 的 SHA 哈希计算器显示每个摘要的十六进制和 base64,使其易于转换或与其他系统交叉引用。
这不包括什么 - 每个工具使用的特定编码(十六进制与 Base64),在单独的帖子中介绍
内容寻址并非特定于密码学,尽管密码散列使其安全。 CRC32 校验和也是内容地址数据,但 CRC32 冲突很常见,并且可以制造冲突;此存储库不会将 SHA-256 标记为损坏,而 CRC32 不作为对抗完整性原语提供。哈希算法的选择对于安全性至关重要:SHA-256 是需要针对对手进行完整性保护的系统的现代标准。 SHA-1 只是遗留的(Git 和其他人正在迁移)。选择正确的算法与选择内容寻址作为命名方案是不同的决定。
内容寻址与加密哈希相结合是现代软件供应链完整性的基础。您安装的每个包、运行的每个容器以及签出的每个提交都可以被验证为原始发布者预期的字节,而无需依赖安全传输(尽管安全传输仍然是良好的做法)。
要点:哈希值就是身份 — ToolAcre SHA 哈希计算器可让您计算这些系统所依赖的相同摘要
内容寻址与编码、存储位置或传输机制无关。无论是存储在本地、CDN、注册表中还是通过 HTTP 或安全 HTTPS 传输,相同的字节都会生成相同的摘要。摘要是对字节的加密承诺,验证它只需要字节和算法,不需要任何外部服务。这就是内容寻址支持离线验证的原因:您可以通过不受信任的渠道下载文件,检查摘要并了解字节是否真实。
ToolAcre SHA 哈希计算器可让您计算这些系统所依赖的相同摘要。粘贴字符串或监视文件,运行计算器并查看 Docker、Git、npm 和其他工具内部使用的 SHA-256、SHA-384 和 SHA-512 摘要。将计算出的摘要与原始源中的摘要进行比较,以验证字节是否未被修改。计算器对您粘贴的 UTF-8 文本进行哈希处理;它不会散列文件或密钥材料,因此它可以散列的内容(文本输入)和不能散列的内容(二进制文件、编码形式的加密密钥)之间的界限是明确的并记录在案。