什么是 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. 填充。 在消息末尾加一个 1 位,再补若干个 0,最后附上原始长度(64 位整数),使总长度成为 512 位的整数倍。
  2. 分块。 把填充后的消息切成若干个 512 位的块。
  3. 压缩。 每个块都要经过 64 轮针对 32 位字的简单运算:循环移位、XOR、AND 以及模 2³² 加法。这些运算把块的内容混入一个由八个 32 位字组成的内部状态(8 × 32 = 256 位)。
  4. 输出。 处理完最后一个块后,内部状态就是哈希值。

每个块都会改变下一个块的起始状态,因此输入中任何位置的改动都会影响最终结果。

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 用在哪里

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 校验和

  1. 从官方下载页面或校验和文件中复制预期的 SHA-256 值。
  2. 计算你下载的文件的哈希值。
  3. 比较全部 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。

两点限制:整个文件会先载入内存,因此对于几 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 哈希相同的不同输入,所以哈希值一致就被视为两个文件完全相同的证明。

免费试用:在线文本哈希 免费使用,无需注册账号。