什么是 SHA-256?工作原理、MD5 与 SHA-256 对比及校验和
SHA-256 是一种密码学哈希函数,能把任意输入(从一个字母到几 GB 的文件)转换成固定长度的 256 位值,通常写成 64 个十六进制字符。它属于 SHA-2 家族,由 NIST 于 2002 年在 FIPS 180-2 中发布。相同的输入总是得到相同的哈希值,而且无法从哈希值还原出输入。
免费试用:在线文本哈希 免费使用,无需注册账号。
那么,SHA-256 是什么、在实际中有什么用?主要用来证明数据没有被改动:下载文件的校验和、TLS 证书、Git、比特币以及带签名的 API 请求都依赖它。本文讲解 SHA-256 的工作原理、MD5 与 SHA-256 的区别、什么是校验和,以及如何在 Windows、macOS 和 Linux 上校验 SHA-256 校验和。文中每个哈希值都用代码计算并核对过两遍。想亲自试试这些例子,可以把它们粘贴到免费的哈希生成器中。
SHA-256 是什么?
SHA 是 Secure Hash Algorithm(安全哈希算法)的缩写。SHA-2 由美国国家安全局(NSA)设计、NIST 标准化,最早见于 FIPS 180-2(2002 年),现行版本为 FIPS 180-4。这个家族有多个成员,按输出长度命名:SHA-224、SHA-256、SHA-384 和 SHA-512,另外还有 SHA-512/224 和 SHA-512/256。其中 SHA-256 使用最广。
哈希值就像数据的指纹。下面是单词 "hello" 和空输入的 SHA-256 哈希示例:
SHA-256("hello") = 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
SHA-256("") = e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
两个结果长度相同,因为输出始终是 256 位,即 32 字节。一个十六进制数字表示 4 位,所以需要 256 ÷ 4 = 64 个十六进制字符。
SHA-256 的工作原理(简述)
- 填充。 在消息末尾加一个 1 位,再补若干个 0,最后附上原始长度(64 位整数),使总长度成为 512 位的整数倍。
- 分块。 把填充后的消息切成若干个 512 位的块。
- 压缩。 每个块都要经过 64 轮针对 32 位字的简单运算:循环移位、XOR、AND 以及模 2³² 加法。这些运算把块的内容混入一个由八个 32 位字组成的内部状态(8 × 32 = 256 位)。
- 输出。 处理完最后一个块后,内部状态就是哈希值。
每个块都会改变下一个块的起始状态,因此输入中任何位置的改动都会影响最终结果。
SHA-256 的关键特性
- 确定性。 相同的字节在任何计算机上都得到相同的哈希值。
- 长度固定。 5 字节的单词和 5 GB 的文件都输出 64 个十六进制字符。
- 雪崩效应。 输入的微小变化会让输出完全改变。
- 抗原像性。 给定一个哈希值,除了猜测之外,没有已知方法能找到对应的输入。
- 抗碰撞性。 至今没有人找到两个哈希值相同的不同 SHA-256 输入。
雪崩效应很直观。"hello" 和 "Hello" 只差一个字母,而字母 h(01101000)和 H(01001000)只差一位:
SHA-256("hello") = 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
SHA-256("Hello") = 185f8db32271fe25f561a6fc938b2e264306ec304eda518007d1764826381969
这两个哈希值在 256 位中有 125 位不同,接近随机输出应有的一半;在 64 个十六进制字符中有 61 个不同。
有一点要注意:抗原像性保护的是不可预测的数据,而不是容易猜到的短字符串。"hello" 的哈希值在网上任何查询表里都能查到,因为谁都可以对常用词计算哈希并保存结果。
什么是校验和?
校验和(checksum)是根据数据计算出的一个简短值,用来在之后判断数据是否被改动。像 CRC32 这样的简单校验和用于 ZIP 文件和网络数据包,能发现下载损坏、磁盘故障等意外错误,但很容易被人为伪造。
把 SHA-256 当作校验和,还能防范蓄意篡改,因为没有人能构造出一个与原始值相同的修改版文件。前提只有一个:预期的哈希值必须来自可信来源,例如项目的官方 HTTPS 网站或带签名的校验和文件。能控制下载页面的攻击者,可以同时替换文件和公布的哈希值。
SHA-256 用在哪里
- 软件下载。 Linux 发行版和许多应用会为安装包公布 SHA-256 校验和,通常放在
SHA256SUMS文件中。 - TLS 证书。 保护 HTTPS 网站的证书大多是基于 SHA-256 哈希签名的,显示为 "sha256WithRSAEncryption" 或 "ecdsa-with-SHA256"。主流浏览器在 2017 年停止信任用 SHA-1 签名的证书。
- 比特币。 矿工对区块头做两次 SHA-256(双重 SHA-256),并不断修改一个叫 nonce 的数字,直到结果低于目标值。这个搜索过程就是工作量证明(proof of work)。
- Git。 Git 传统上用 SHA-1 哈希来命名提交和文件。从 2.29 版(2020 年)起,
git init --object-format=sha256可以创建改用 SHA-256 的仓库。 - HMAC-SHA256 和 JWT。 HMAC 把密钥混入哈希计算,只有持有密钥的人才能生成有效值。Webhook 和 API 请求常用这种方式签名,JWT 的 HS256 算法就是基于 SHA-256 的 HMAC;HMAC 生成器可以计算这个值。不要用简单的
SHA-256(key + message)代替:它容易受到长度扩展攻击,而 HMAC 能防止这种攻击。
MD5 与 SHA-256(以及 SHA-1、SHA-512)对比
| 算法 | 输出 | 十六进制字符数 | 发布 | 安全状况 |
|---|---|---|---|---|
| MD5 | 128 位 | 32 | 1992(RFC 1321) | 已攻破:自 2004 年起可实际构造碰撞 |
| SHA-1 | 160 位 | 40 | 1995(FIPS 180-1) | 已攻破:2017 年首次公开碰撞 |
| SHA-256 | 256 位 | 64 | 2002(FIPS 180-2) | 安全:没有已知碰撞 |
| SHA-512 | 512 位 | 128 | 2002(FIPS 180-2) | 安全:没有已知碰撞 |
同一个输入分别用四种算法计算:
MD5("hello") = 5d41402abc4b2a76b9719d911017c592
SHA-1("hello") = aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d
SHA-256("hello") = 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
SHA-512("hello") = 9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca72323c3d99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043
MD5 是什么? MD5 是 1992 年推出的较老的 128 位哈希算法。2004 年,王小云领导的研究团队展示了如何构造两个 MD5 哈希相同的不同输入,后续研究又让这类碰撞可以快速算出。在有人可能故意构造匹配文件的场景中,不能使用 MD5。
SHA-1 撑得更久一些。2017 年 2 月,荷兰 CWI 研究所和 Google 公布了 SHAttered:两个内容不同但 SHA-1 哈希相同的 PDF 文件。NIST 建议在 2030 年 12 月 31 日前彻底停用 SHA-1。
SHA-256 目前没有已知的实用攻击。用暴力搜索找碰撞大约需要 2¹²⁸ 次尝试,远远超出任何现有计算机的能力。
所以在 MD5 与 SHA-256 之间选择时,凡是与安全相关的场景都应使用 SHA-256。在没有人试图欺骗你的场合,MD5 仍然可用,例如检测意外损坏或查找自己硬盘上的重复文件。
SHA-256 和 SHA-512 都是安全的;SHA-256 是支持最广泛的默认选择。SHA-3(FIPS 202,2015 年)是另一种独立设计,作为备选方案被标准化,并不是因为 SHA-2 被攻破。
哈希不是加密
加密(例如 AES)是可逆的:有正确的密钥就能还原原始数据。哈希没有密钥,也没有回头路;无论输入多大,输出始终是 256 位,所以原始数据根本不在输出里。声称能“解密 SHA-256”的网站,只是在查找预先算好的常用词和常用密码的哈希值。
为什么不能直接用 SHA-256 存储密码
SHA-256 的设计目标是快,而这恰恰是存储密码时的问题。一旦存有 SHA-256 密码哈希的数据库泄露,攻击者可以用显卡每秒尝试数十亿次猜测。如果不加盐,两个使用相同密码的用户还会得到相同的哈希值。
密码需要慢速、加盐的密码哈希函数:Argon2id、scrypt 或 bcrypt(或者迭代次数足够多的 PBKDF2)。它们让每一次猜测都代价高昂。关于盐以及哈希密码泄露后会发生什么,请阅读密码被哈希时会发生什么。
如何校验 SHA-256 校验和
- 从官方下载页面或校验和文件中复制预期的 SHA-256 值。
- 计算你下载的文件的哈希值。
- 比较全部 64 个字符,而不只是前几个。十六进制不区分大小写。
如果两个值不一致,请删除该文件,并从官方来源重新下载。
Windows
在命令提示符中:
certutil -hashfile ubuntu.iso SHA256
一定要加上 SHA256:不加的话,certutil 会使用 SHA-1。在 PowerShell 中,Get-FileHash 默认使用 SHA-256,还可以替你完成比较:
Get-FileHash .\ubuntu.iso
(Get-FileHash .\ubuntu.iso).Hash -eq "paste-the-expected-hash-here"
第二行会输出 True 或 False;-eq 不区分大小写,所以大写的输出也能和小写的校验和匹配。
macOS
shasum -a 256 ubuntu.iso
shasum -a 256 -c ubuntu.iso.sha256
第一行输出哈希值。第二行根据校验和文件进行校验,该文件的内容是哈希值、两个空格和文件名。
Linux
sha256sum ubuntu.iso
sha256sum -c SHA256SUMS --ignore-missing
加上 -c 后,sha256sum 会读取校验和文件,并输出 ubuntu.iso: OK 或 FAILED。--ignore-missing 会跳过你没有下载的文件对应的条目。
在命令行中对文本计算哈希时有个常见陷阱:echo "hello" | sha256sum 得到的是 5891b5b522d5df086d0ff0b110fbd9d21bb4fc7163af34d08286a2e846f6be03,而不是上文的 2cf24d…,因为 echo 会追加一个换行符。请用 printf 'hello' | sha256sum,这样哈希的正好是五个字节。
在浏览器中
MD5 与 SHA-256 哈希生成器可在“文本”或“文件”模式下同时计算 MD5、SHA1、SHA224、SHA256、SHA384、SHA512、Keccak-256 和 RIPEMD160。
- 文本: 按 UTF-8 对你输入的内容原样计算哈希,并有计数器显示字节数,多出来的空格或换行一眼就能发现。
- 文件: 文件在本地用 crypto-js 库读取并计算哈希,不会上传。
- 校验: 把公布的值粘贴到“预期哈希”框中,匹配的算法会被标记为“匹配”。十六进制比较会忽略大小写、空格和
0x前缀。 - 输出: 十六进制(小写或大写)、Base64、Base64url 或二进制。
两点限制:整个文件会先载入内存,因此对于几 GB 的 ISO 文件,上面介绍的命令行工具是更好的选择。另外,标为 SHA3 的那一行是采用原始填充方式的 Keccak-512,与 NIST 的 SHA3-512 结果不同。
常见问题
SHA-256 能被解密或逆推吗?
不能。SHA-256 是没有密钥的单向函数。所谓的“SHA-256 解密器”只能找到早已存在于其查询表里的输入,对常用词和弱密码有效,对随机数据则无效。
SHA-256 现在还安全吗?
安全。目前没有针对 SHA-256 的实用碰撞攻击或原像攻击,NIST 也仍然批准使用它。就目前所知,即使是运行 Grover 算法的大型量子计算机,也只能把寻找原像的工作量从约 2²⁵⁶ 次运算降到约 2¹²⁸ 次。
为什么 SHA-256 哈希值是 64 个字符?
哈希值有 256 位。用十六进制书写时,每个字符表示 4 位,所以 256 ÷ 4 = 64 个字符。同一个值也是 32 字节,用 Base64 表示则是 44 个字符。
SHA-2 和 SHA-256 有什么区别?
SHA-2 是 FIPS 180-4 定义的哈希函数家族,SHA-256 是其中一员,其他成员还有 SHA-224、SHA-384 和 SHA-512。软件中只写 “SHA-2” 而不注明长度时,通常指的是 SHA-256。
两个文件可能有相同的 SHA-256 哈希值吗?
理论上可能,因为可能的文件有无穷多个,而可能的哈希值只有 2²⁵⁶ 个。但实际上,至今没有人找到过两个 SHA-256 哈希相同的不同输入,所以哈希值一致就被视为两个文件完全相同的证明。
免费试用:在线文本哈希 免费使用,无需注册账号。