SSD Nodes Learn Hosting plans →
指南 Matt Connor作者: Matt Connor · 更新于 2026-08-25

Linux如何使用SHA256校验和验证下载文件

学习使用 sha256sum 生成并验证 SHA256SUMS 文件,观察修改一个字节后出现的“FAILED”结果,并理解校验和无法证明摘要来源。

Verified Every command ran end-to-end on a fresh Ubuntu 24.04 server, August 12, 2026.

在两分钟内使用校验和验证下载文件

要使用校验和验证下载文件,请计算收到的文件的哈希值,再让工具将该哈希值与发布者提供的哈希值进行比较。sha256sum可以完成这两步:单独使用时,它会输出摘要;与 -c 一起使用时,它会读取摘要列表,并报告哪些文件匹配。本指南会对您创建的文件执行完整流程,然后故意修改该文件,让您直接观察验证失败,而不是只阅读相关说明。

请始终记住下面这句话。校验和可以告诉您,手中的字节是否就是生成该摘要的字节;但它无法告诉您摘要由谁生成。后一个问题需要使用签名和您信任的密钥。本指南的最后部分会准确说明两者的区别。

创建一个用于练习的文件

在临时目录中操作,确保这里的操作不会影响系统的其他部分。下面的所有命令都来自 GNU coreutils,这是所有 Ubuntu 或 Debian 服务器上都具备的基础命令集,因此无需安装任何软件。

mkdir -p ~/checksum-demo
cd ~/checksum-demo
printf 'the payload of a totally ordinary download\n' > payload.txt
sha256sum payload.txt

输出只有一行:64 个十六进制字符、两个空格,然后是文件名。这 64 个字符是文件的摘要。再次运行该命令,输出内容完全相同,因为哈希计算具有确定性:相同的输入始终产生相同的输出。修改文件中的一个字符后再次运行,摘要不会只发生细微变化。输出看起来会完全不同,因为输入中的一个比特发生翻转,会导致输出中大约一半的比特发生翻转。正是这一特性,使 64 个字符的字符串可以有效代表一个 4 GB 的镜像。

保存 SHA256SUMS 文件,然后进行校验

屏幕上显示的摘要过一天就没有用处了。请将摘要写入文件,并使用 sha256sum 自身写出的格式,这样工具之后可以重新读取该文件。

sha256sum payload.txt > SHA256SUMS
cat SHA256SUMS
sha256sum -c SHA256SUMS

sha256sum -c 会读取列表中的每一行,对该行指定的文件计算哈希值,然后比较两个摘要。校验正常时,每个文件输出一行:

payload.txt: OK

同时检查退出状态,因为脚本会读取退出状态,而不会读取文本。校验成功后,echo $? 会输出 0。SHA256SUMS 这个名称是一种约定,并非强制要求,但各发行版和大多数发布页面都使用它。因此也应使用该名称,这样后续人员无需打开文件即可知道其中的内容。

翻转一个字节并观察校验失败

现在故意破坏文件。此命令只会修改偏移量 5 处的一个字节,其他内容保持不变,因此文件的长度和名称都不会改变。

printf 'X' | dd of=payload.txt bs=1 seek=5 conv=notrunc status=none
cat payload.txt
sha256sum -c SHA256SUMS

conv=notrunc 是关键标志。没有它,dd 会在停止写入的位置截断文件,你测试的将是更明显的损坏类型。现在,校验会输出:

payload.txt: FAILED
sha256sum: WARNING: 1 computed checksum did NOT match

echo $? 输出 1。FAILED 表示文件已读取,但其摘要与列表中的摘要不匹配。恢复原始字节,并确认校验恢复为 OK:

printf 'the payload of a totally ordinary download\n' > payload.txt
sha256sum -c SHA256SUMS

完整流程就是这样。文件中的任意位置只要有一个字节不同,就会产生 FAILED。因连接中断而提前结束的下载、提供昨天构建版本的镜像站、在传输过程中重写文件的代理、返回坏块数据的磁盘,最终都会显示为同一行。

当列表中列出了您未下载的文件

发行版提供的真实 SHA256SUMS 文件会列出项目发布的所有镜像,而您只下载了其中一个。下面复现这种情况。

printf 'a second file\n' > notes.txt
sha256sum payload.txt notes.txt > SHA256SUMS.all
rm notes.txt
sha256sum -c SHA256SUMS.all
payload.txt: OK
sha256sum: notes.txt: No such file or directory
notes.txt: FAILED open or read
sha256sum: WARNING: 1 listed file could not be read

FAILED open or read 与 FAILED 是不同的故障。混淆二者会浪费时间。FAILED 表示文件内容不正确。FAILED open or read 表示 sha256sum 根本没有找到该文件,因此没有进行比较。在实际下载中,常见原因是当前工作目录不正确,因为列表中的文件名是相对于运行命令时所在目录的路径。切换到存放该文件的目录,然后再次运行命令。若只想检查实际拥有的文件,可以使用以下命令:

sha256sum --ignore-missing -c SHA256SUMS.all

该命令会输出 payload.txt: OK,并以退出码 0 结束。如果列表中的文件名一个都不存在,--ignore-missing 不会在零个文件上静默成功。它会报告 no file was verified,并以非零退出码结束。这正是需要的行为,因为检查了零个文件却显示通过,会导致您永远无法发现故障。

直接粘贴发布的摘要,不要凭肉眼读取

逐个比较64个十六进制字符时,凭肉眼检查最容易出错。人们会查看开头4个字符和结尾4个字符,然后认为两者匹配;而这正是有针对性的攻击者预期你会采用的比较方式。让工具执行比较。使用 EXPECTED= 加上粘贴的摘要值,将从发布者处复制的摘要设置到 EXPECTED,然后生成 -c 所需的单行内容:

printf '%s  %s\n' "$EXPECTED" payload.txt > payload.sha256
cat payload.sha256
sha256sum -c payload.sha256

摘要和文件名之间有两个空格,因此格式字符串中也包含两个空格。这正是 sha256sum 写入的格式,也是 -c 解析的格式。只包含摘要而没有其他内容的文件并不是校验和行,因此校验会使用 no properly formatted checksum lines found 拒绝整个文件,而不是猜测你要校验的是哪个文件。有些项目发布的是 BSD 标记格式,即 SHA256 (payload.txt) = 后跟摘要。GNU coreutils 使用 sha256sum --tag payload.txt 写入这种格式,并使用 -c 读取,因此保存任一种格式都可以。

校验行为异常时,使用 cat -A SHA256SUMS 查看列表本身。该命令会用 $ 标记每行的结尾,并显示其他情况下不可见的字符。以 ^M$ 结尾的行可能从 Windows 编辑器中带入了回车符。GNU sha256sum 会忽略末尾的该字符,并仍然输出 OK,因此 CRLF 列表不是导致校验失败的原因,但 coreutils 之外的工具对这种情况通常不够宽容。使用 tr -d '\r' < SHA256SUMS > SHA256SUMS.clean 规范化要保留的副本。

校验和能证明什么,不能证明什么?

校验和只能证明一件事:磁盘上的字节与生成已发布摘要的字节相同。这可以完全发现意外损坏。如果攻击者替换了下载镜像上的文件,但无法修改发布摘要的页面,校验和也可以发现这种篡改。

校验和无法证明文件的作者。摘要反映的是字节这一事实,而不是人员这一事实。如果同一个页面同时提供文件和摘要,那么能够修改其中一个的人也能修改另一个。此时,您的 OK 行只能说明镜像与自身一致。因此,运行校验和必须遵循以下规则:从与文件不同的位置获取摘要。例如,镜像或 torrent 提供映像,而您通过 TLS(传输层安全)从项目自己的域名获取摘要。这样,攻击者必须同时控制两个位置,而不是一个位置。校验和同样无法说明运行这些已验证的字节后会发生什么。对于任何代表您执行操作的内容,都应单独考虑这个问题,例如安装脚本,或以您的代理权限运行的 dsh 插件。

算法同样重要。截至 2026 年 8 月,SHA-256(安全哈希算法,256 位输出)尚无已知碰撞,因此发布者会使用它。MD5(消息摘要 5)和 SHA-1 已无法满足要求:自 2004 年起,就可以构造出具有相同 MD5 摘要的两个不同文件;2020 年还公开了选定前缀的 SHA-1 碰撞。MD5SUMS 文件仍可以发现下载截断,因为随机损坏不是精心构造的碰撞。但它无法阻止试图欺骗您的攻击者。如果项目同时发布两者,请使用 SHA-256 行。

签名发挥作用的地方

签名弥补了摘要留下的缺口。发布者使用私钥对摘要文件进行签名,然后您使用其公钥进行验证:gpg --verify SHA256SUMS.asc SHA256SUMS。验证通过后,说明摘要列表来自持有该密钥的一方。接着,sha256sum -c SHA256SUMS会将磁盘上的文件与该列表关联起来,整条信任链就从密钥一直延伸到文件字节。

薄弱点转移到了密钥。若从提供文件的同一页面获取密钥,攻击者就能同时替换文件和密钥。GnuPG 会明确提示这一点;首次验证时会输出 Good signature,以及 WARNING: This key is not certified with a trusted signature!。Good signature表示数学验证成立,但不表示该密钥属于您所信任的项目。应从第二个来源获取指纹,例如项目在其他域名上的文档,或已经随发行版提供该密钥的软件包,然后比较完整指纹,而不是只比较最后 8 个字符。这与SSH 私钥需要同样谨慎,原因相同:密钥决定信任关系,后续所有内容都会继承这一信任。

可复现构建将这一理念进一步推进。已发布的摘要仍然意味着您必须信任由某台机器构建的二进制文件。如果项目支持可复现构建,任何人都可以从相同源代码进行编译,并获得逐字节一致的输出。这样,独立构建者就能确认已发布的摘要,而不必要求您相信某台服务器的结果。随着越来越多的代码通过自动化流水线和机器编写的补丁交付,这一点变得更加重要。决定哪些内容可以纳入构建属于策略问题,面向 AI 辅助代码的开源策略也从供应链的另一端处理同一问题。

软件包管理器会自动完成这些操作

在 Debian 和 Ubuntu 上,apt 每次安装软件包时都会自动执行这条验证链。软件包索引为每个 .deb 文件提供 SHA-256 摘要。Release 文件包含这些索引文件的摘要,InRelease 则包含针对 Release 的签名;系统会使用 /usr/share/keyrings 和 /etc/apt/trusted.gpg.d 中的密钥验证该签名。验证链中断时,apt 会明确报告原因:第三方软件源缺少密钥时显示 The following signatures couldn't be verified because the public key is not available: NO_PUBKEY;获取到的索引与已签名的 Release 不匹配时显示 Hash Sum mismatch。后者通常表示缓存代理提供了过期文件,或你在镜像同步过程中获取了文件。

当项目主页要求你将来自 curl 的脚本直接通过管道传给 shell 时,应以此标准进行判断。此时不会验证字节内容,你也无法查看脚本内容。服务器还可以向脚本返回一种内容,向浏览器返回另一种内容,而且之后没有副本可供检查。使用 curl -fsSL <url> -o install.sh 将脚本下载到文件,计算其哈希值,使用 less 阅读内容,然后再运行。这个习惯大约只需二十秒;在安装其他任何内容之前,也值得在 全新 VPS 的最初十分钟内养成这一习惯。

记录手动安装内容的摘要列表

apt安装的软件包会被跟踪。手动复制到 /usr/local/bin 的二进制文件不会被跟踪,系统中也没有任何机制监控它。摘要列表可以将其转化为按需检查的内容:

printf 'a second file\n' > notes.txt
sha256sum *.txt > inventory.sha256
sha256sum -c --quiet inventory.sha256

所有文件都匹配时,--quiet 不输出任何内容;部分文件不匹配时,它只输出检查失败的行。因此,没有输出表示检查通过,echo $? 会通过 0 确认这一点。这种形式适合放入定时任务。--status 更进一步,完全不输出内容,只保留退出状态。使用 sha256sum /usr/local/bin/* > ~/local-bin.sha256 将同样的模式应用于实际文件,即可建立基线。路径会按输入时的原样存储在列表中,因此使用绝对路径后,无论从哪个目录运行检查都有效。

必须明确这个基线的作用。它可以检测文件是否发生变化,但无法检测已经获得 root 权限的攻击者,因为该攻击者可以像改写二进制文件一样轻易地改写 inventory.sha256。如果希望这份列表具有实际意义,请将其保存在这台计算机之外。这也是更大问题的一部分:您实际信任 VPS 的程度,以及还有谁能够访问其底层磁盘。

FAQ

匹配的校验和是否意味着下载内容安全?

不是。这表示您拥有的字节与用于比对的摘要一致。如果攻击者控制了发布该摘要的页面,就可以发布其自有文件的摘要,您的检查会输出 OK。匹配只能说明内容一致。要确认安全性,必须使用从其他来源获取的密钥验证签名;只有这样,摘要才继承该密钥的信任。

为什么 sha256sum -c 会输出 FAILED open or read?

因为它根本没有读取该文件。它上方紧邻的一行会显示 No such file or directory 以及它查找的文件名。SHA256SUMS 文件中的文件名是相对于运行命令所在目录的路径,因此请切换到存放下载文件的目录后重新运行。如果列表中还包含您未下载的文件,请添加 --ignore-missing。不带 open or read 的普通 FAILED 表示相反情况:文件已被读取,但其摘要不匹配。

使用 MD5 验证下载是否足够?

如果只是检查意外损坏,可以。传输被截断或磁盘块损坏,不会偶然生成匹配的 MD5 摘要。但如果要防范攻击者,则不够。自 2004 年起,已经可以构造出具有相同 MD5 摘要的不同文件;2020 年,SHA-1 也被攻破,出现了选择前缀碰撞。项目同时发布 SHA-256 和 MD5 时,请使用 SHA-256;如果项目只提供 MD5,应将其视为发布流程陈旧的信号。

sha256sum -c 与 gpg --verify 有什么区别?

sha256sum -c 证明文件与摘要匹配。gpg --verify 证明摘要文件由特定私钥的持有者签名。它们回答的是不同问题,因此项目同时提供两者时,应同时运行这两项检查。签名使摘要列表可信,摘要列表再使下载文件可信。

如何将单个文件与网页上显示的摘要进行比对?

不要用肉眼比较字符。将摘要和文件名保存到同一行,中间使用两个空格分隔,然后对该文件运行 sha256sum -c,并查看它输出的 OK 或 FAILED。使用 printf '%s %s\n' 构造这一行,可以避免格式错误;这些错误会导致 sha256sum 以 no properly formatted checksum lines found 拒绝该文件。

#checksums#sha256sum#integrity#supply-chain#安全