Skip to content
返回博客
教程

SHA-1 vs SHA-256 vs SHA-512:2026 哈希算法选择指南

SHA-1、SHA-256、SHA-384、SHA-512 和 SHA-3 的安全现状、输出长度、性能与真实使用场景全面对比。附决策树与常见陷阱。

14 分钟

SHA-1 vs SHA-256 vs SHA-512:2026 年如何选对哈希算法

打开一张 TLS 证书、一个 Git 对象数据库、一个 Bitcoin 区块头、一个 Linux 包管理器,或一份 Docker 镜像清单 —— 每一个里面都有 SHA 哈希。但用的不是同一种 SHA。SHA-1、SHA-256、SHA-384、SHA-512、SHA-3:这个家族横跨三十年、两条设计谱系,以及一次碰撞攻击 —— 那次攻击彻底打垮了其中最老的成员。

本文梳理整个 SHA 家族的全貌,让你在面对具体场景时可以直接拿定主意,不用反复纠结。

快速决策树

在深入细节之前,先看一张大多数开发者真正需要的汇总表:

你的场景最佳选择原因
TLS/HTTPS 证书SHA-256(最低要求),高安全级别用 SHA-384CA/Browser Forum 基线要求强制规定
JWT 签名(HMAC 或 RSA)SHA-256(HS256/RS256)通用支持;合规场景可用 SHA-384/512
软件完整性校验和SHA-256行业默认,广为人知
归档或长期完整性SHA-512输出更长,未来几十年都有充足安全余量
内容寻址(IPFS、OCI)SHA-256内容寻址存储的事实标准
Git(读写现有仓库)现有仓库用 SHA-1;新建仓库用 --object-format=sha256SHA-256Git 正在迁移中;SHA-1 仍占主导
与 Ethereum 互操作Keccak-256(非 NIST SHA-3)Ethereum 使用标准化之前的 Keccak 变体
纵深防御或涉密系统SHA-384SHA-512NSA Suite B;与 AES-256-GCM 配套
全新代码,无历史包袱SHA-3(SHA3-256)不同设计谱系;天然免疫长度扩展攻击
密码存储以上都不用请用 bcrypt、Argon2id 或 scrypt —— SHA 太快了

SHA 家族一览

算法标准输出位数十六进制字符数发布年份NIST 状态当前主要用途
SHA-1FIPS 180-4160401995已废弃(2011),数字签名用途已撤销Git 遗留、指纹
SHA-256FIPS 180-4256642001现行TLS、JWT、Bitcoin、校验和
SHA-384FIPS 180-4384962001现行Suite B、高安全 TLS
SHA-512FIPS 180-45121282001现行归档、LUKS、HMAC-SHA-512
SHA-3(任意变体)FIPS 202224/256/384/512不等2015现行备选谱系、硬件加速场景

SHA-1 和 SHA-2(256/384/512 这一组)共用 Merkle-Damgard 构造。SHA-3 使用海绵构造 —— 这个区别比看上去更重要,下文详述。

SHA-1:破了,但还没死

SHA-1 是 2000 年代的主力算法。SSL 证书、S/MIME 邮件、PGP 指纹、Git 都汇聚到它身上。然后在 2017 年 2 月,Google 与 CWI Amsterdam 联合发布了 SHAttered:一次选择前缀碰撞攻击,生成了两份哈希值完全相同的不同 PDF 文件。这次攻击消耗了大约 6.5 × 10^19 次 SHA-1 计算 —— 2017 年时代价高昂,但以今天的云计算价格来看已触手可及。

NIST 早在 2011 年就已在 NIST Special Publication 800-131A 中废弃了 SHA-1 的数字签名用途。SHAttered 演示加速了清理进程:各大浏览器在 2017 年停止信任 SHA-1 TLS 证书,CA/Browser Forum 将 SHA-256 定为新证书签发的强制要求。

SHA-1 仍在使用的场景:

  • Git 对象数据库:Git 最初设计时把 SHA-1 当作快速内容哈希,而非安全原语。仓库格式把 40 个十六进制字符的对象 ID 硬编码进去了。迁移到 SHA-256 的路径(git init --object-format=sha256)已经存在,但落地缓慢 —— 因为每个托管平台、每个 CI 工具和每个现有克隆都需要同步迁移。
  • 遗留系统指纹:旧的 SSH 主机密钥指纹、PGP 密钥指纹和证书序列号方案中仍然暴露 SHA-1 值。在大多数场景下这些是信息展示用途,并非安全关键。

该怎么做:不要在任何新项目中使用 SHA-1。对于 Git,典型的软件开发工作流中碰撞风险较低(攻击者需要同时控制碰撞中的两个文件),但新项目使用 --object-format=sha256 才是正确的长期方向。

在浏览器中生成 SHA-1 哈希:SHA-1 生成器

SHA-256:主力算法

SHA-256 是 2026 年支撑互联网运转的算法。每一张由公共 CA 签发的 TLS 证书,其签名哈希都是 SHA-256。每一个用 HS256、RS256 或 ES256 签名的 JWT,内部都用了 SHA-256。Bitcoin 的工作量证明是双重 SHA-256。Docker 内容哈希是 SHA-256。npm 包完整性也使用 SHA-256。

原因很实际:

  • 安全余量:256 位输出意味着暴力原像攻击需要 2^128 次操作 —— 在可预见的未来超出任何硬件的能力。实际安全级别因生日界碰撞攻击(2^128 次操作)略低一点,但依然无法撼动。
  • 硬件加速:SHA-256 在每块 Intel Goldmont+ CPU(SHA-NI 扩展)、每块 Apple Silicon 芯片、每块 ARMv8 处理器,以及网络设备和存储控制器的专用 ASIC 上都有硅级实现。走硬件路径时,SHA-256 的吞吐量超过许多看起来”更快”的纯软件替代方案。
  • 无处不在的库支持:每个 TLS 库、每个 JWT 库、每种语言的标准库都实现了 SHA-256。你不会碰到兼容性壁垒。

对于内容寻址、完整性验证和大多数签名工作流,SHA-256 是正确的默认选择,除非特定标准另有要求。

在浏览器中生成 SHA-256 哈希:SHA-256 生成器

SHA-384:TLS 专属算法

SHA-384 是将 SHA-512 截断到 384 位的产物。它被设计为提供 192 位安全级别(输出长度的一半是碰撞抗性下界),并与 AES-256-GCM 和 P-384 椭圆曲线密钥一起被纳入 NSA Suite B 密码学方案。

SHA-384 在 TLS 场景中格外有吸引力,原因有两点:

  1. 在该输出长度下免疫长度扩展攻击:SHA-256 和 SHA-512 容易受到长度扩展攻击 —— 知道 H(secret || message) 的攻击者,无需知道密钥就能计算出 H(secret || message || extension)。SHA-384 和 SHA-512/256 是从完整内部状态截断而来的,因此长度扩展不适用。如果你用原始 SHA 哈希作为 MAC(而非 HMAC),SHA-384 更安全。
  2. Suite B 合规要求:需要满足 NSA/CNSA(商业国家安全算法)套件要求的组织,必须将 SHA-384 或 SHA-512 与 RSA-3072+、ECDH P-384 和 AES-256 配合使用。如果你的客户是美国联邦机构或在 FIPS 140-3 要求下运营的承包商,SHA-384 可能是强制规定。

对大多数使用场景来说,SHA-384 并不比 SHA-256 更安全 —— 在当前算力水平下,128 位和 192 位碰撞抗性之间的实际差距只是理论上的。只有在合规要求或 Suite B 配套要求时才选它,不要用于通用场景。

在浏览器中生成 SHA-384 哈希:SHA-384 生成器

SHA-512:需要更长输出时的选择

SHA-512 生成 512 位(128 个十六进制字符)的摘要。在 64 位硬件上,它往往比 SHA-256 快,因为该算法在 64 位字上运算,而非 32 位字 —— SHA-256 的内部调度使用 32 位算术,而 SHA-512 使用 64 位算术,更高效地映射到现代 CPU 上。

64 位硬件上的基准测试(参考值;浏览器 Web Crypto API):

算法近似吞吐量
SHA-1~600 MB/s
SHA-256~500 MB/s
SHA-384~700 MB/s
SHA-512~700 MB/s
SHA-3-256~300 MB/s

注:SHA-384 和 SHA-512 共用相同的内部压缩函数,因此速度相同。SHA-256 在 64 位平台上更慢,是因为其 32 位字长意味着每个 512 位消息块需要更多迭代。在 32 位或受限硬件上,SHA-256 更快。

SHA-512 适合以下场景:

  • 归档完整性:旨在存活数十年的校验和,从更大的输出余量中受益。
  • 全盘加密:Linux LUKS 默认将 SHA-512 用作密钥派生 PBKDF 哈希(作为 PBKDF2 的组件,而非独立哈希)。
  • HMAC-SHA-512:用于部分 JWT 签名方案(HS512)以及偏好更大 MAC 的 API 认证。
  • 生成大量伪随机数据:对种子进行哈希并需要大量输出位的应用,可以用 SHA-512 减少哈希调用次数。

在浏览器中生成 SHA-512 哈希:SHA-512 生成器

SHA-3:截然不同的设计哲学

SHA-3 不是输出更长的 SHA-2,而是一种基于海绵构造(称为 Keccak)的全新算法,由 Guido Bertoni、Joan Daemen、Michaël Peeters 和 Gilles Van Assche 设计。NIST 在一场历时七年的公开竞赛(2007–2012 年)中选出它作为胜者,目的是在 SHA-2 的 Merkle-Damgard 构造被发现弱点时,能有一个备用哈希家族。

海绵构造的工作方式与 Merkle-Damgard 不同:

  1. 输入被填充并拆分成块。
  2. 每个块与大型内部状态的前一部分(“rate”)进行 XOR,然后用 Keccak-f 置换对整个状态进行置换。
  3. 吸收所有输入后,从状态的 rate 部分”挤出”输出。

由于输出只从状态的一部分提取,而容量部分从不直接暴露,海绵构造天然免疫长度扩展攻击,无需截断。

SHA-3 标准变体(FIPS 202):

变体输出位数安全级别
SHA3-224224112 位
SHA3-256256128 位
SHA3-384384192 位
SHA3-512512256 位
SHAKE128可变128 位
SHAKE256可变256 位

SHA-3 与 SHA-2 的实际对比:

SHA-3 在 2015 年之前设计的协议中尚未广泛部署 —— TLS、JWT 和大多数互联网基础设施仍然使用 SHA-2。SHA-3 正在出现于后量子签名方案(CRYSTALS-Dilithium、SPHINCS+ 内部使用 SHA-3)、希望引入不同谱系备份的新协议设计,以及 Keccak 置换加速良好的硬件中。在纯软件实现中,SHA-3 在 x86 上比 SHA-256 大约慢 40%。

在浏览器中生成 SHA-3 哈希:SHA-3 生成器

Ethereum 的 Keccak-256 区分

一个关键的坑:Ethereum 使用的不是 NIST SHA-3。Ethereum 的设计时间早于 NIST 发布 FIPS 202(2015 年 8 月),那时 Keccak 竞赛还在进行中。Ethereum 虚拟机使用的是 Keccak 的原始提交版本,其填充方式与 NIST 最终确定的 SHA-3 标准不同。

具体而言:

  • NIST SHA3-256 在最后一个块前追加 0x06 填充。
  • 原始 Keccak-256(Ethereum 使用的版本)追加 0x01 填充。

相同输入会产生不同哈希。调用 NIST SHA3-256 与调用 Ethereum 的 keccak256 不可互换。大多数语言两者都有:在 Python 中,hashlib.sha3_256() 是 NIST SHA-3;Ethereum 使用的 Keccak-256 需要类似 pysha3 这样的库(实现 keccak_256)。在 JavaScript 中,js-sha3 库同时暴露两者。SHA-3 生成器实现的是 NIST SHA3-256 —— 如果你需要 Ethereum Keccak-256 哈希,请使用 Ethereum 专用工具。

性能基准

以下数字是在现代 x86-64 笔记本上通过浏览器 Web Crypto API 得到的参考值。实际吞吐量因硬件、消息大小,以及平台是否使用硬件加速路径而异。

算法流式吞吐量(64 位)
SHA-1~600 MB/s
SHA-256~500 MB/s
SHA-384~700 MB/s
SHA-512~700 MB/s
SHA-3-256~300 MB/s

对小消息(API token、几 KB 以内的校验和),所有算法的完成时间都在 2 µs 以内 —— 差异可以忽略不计。对大数据(tarball、磁盘镜像),SHA-384/512 在 64 位系统上胜过 SHA-256,因为它们在 64 位字上运算。SHA-3 在纯软件中较慢;除非有硬件 Keccak 加速,否则吞吐量敏感的代码应优先选 SHA-2。SHA-1 的吞吐量永远不应成为选用它的理由。

常见陷阱

编码不匹配

SHA 在字节上运算。如果你在浏览器中对字符串 "hello" 进行哈希,而 JavaScript 将其编码为 UTF-16 而非 UTF-8,得到的摘要就会与使用 str.encode("utf-8") 的 Python 脚本不同。在哈希文本之前,始终统一转换为 UTF-8。

一个一致的写法:

const encoder = new TextEncoder(); // UTF-8
const data = encoder.encode(inputString);
const hashBuffer = await crypto.subtle.digest("SHA-256", data);

用 MAC 时漏掉加盐

将原始 SHA 哈希用作消息认证码(H(secret || message))容易受到 SHA-256 和 SHA-512 的长度扩展攻击。应使用 HMAC(RFC 2104):HMAC-SHA256(key, message)。HMAC 用内外两层密钥填充包装哈希,从而防止扩展攻击。

SHA-256 的长度扩展攻击

如果你构造 API 签名的方式是 SHA256(secret + payload),那么知道结果哈希的攻击者可以在不知道密钥的情况下计算出 SHA256(secret + payload + attacker_extension)。修复方法:使用 HMAC,或使用 SHA-3(天然免疫),或使用 SHA-384/SHA-512/256(因截断而免疫)。

把 Keccak-256 与 NIST SHA-3 混淆

如上所述:Ethereum 使用 0x01 填充的 Keccak-256;NIST SHA3-256 使用 0x06 填充。对于相同输入,它们产生不同输出。在集成 Ethereum 合约或 Solidity ABI 编码之前,务必确认你的库实现的是哪个变体。

用 SHA 存储密码

SHA 算法被设计为快速运算。而这恰恰是密码存储所不需要的特性:GPU 集群每秒可以计算数十亿次 SHA-256 哈希,使得针对 SHA 哈希密码数据库的字典攻击变得可行。对于密码,请使用内存困难型密钥派生函数:Argon2id(推荐)、bcrypt 或 scrypt。永远不要以原始 SHA 哈希存储密码,即使加了盐也不行。

常见问题

SHA-1 和 SHA-256 有什么区别?

SHA-1 和 SHA-256 都是在 FIPS 180-4 中标准化的 Merkle-Damgard 哈希函数,但 SHA-256 产生 256 位摘要,而 SHA-1 只有 160 位。更重要的是,SHA-1 已经被破解:现实中的碰撞攻击(SHAttered,2017 年)展示了两份 SHA-1 哈希相同的不同 PDF 文件。SHA-256 没有已知的碰撞攻击,提供 128 位碰撞抗性级别。凡是需要完整性保证的场景都应使用 SHA-256;不要在新工作中使用 SHA-1。

SHA-512 比 SHA-256 快吗?

在 64 位硬件上,对大输入通常快 30–40%。SHA-512 使用 64 位字算术,现代 CPU 原生处理。SHA-256 使用 32 位字算术,在同样硬件上每个消息块需要两倍的操作。在 32 位平台或受限微控制器上,SHA-256 更快。对于短消息(几 KB 以内),差异几乎感知不到。

我需要从 SHA-1 迁移到 SHA-256 吗?

对于数字签名、TLS 证书和代码签名:是的,必须迁移 —— SHA-1 已被废弃且存在实际破解。对于 Git 仓库:迁移路径存在(git init --object-format=sha256),但由于生态系统协调需求,落地缓慢;典型仓库使用场景下的碰撞风险较低。对于信息展示型指纹(SSH 主机密钥显示):安全暴露极小,但迁移到 SHA-256 是良好的安全卫生习惯。

SHA-256 可以被逆向吗?

不能。SHA-256 在设计上是单向函数。给定一个哈希,你无法从数学上恢复原始输入。攻击者能做的是跑字典攻击或暴力攻击:对数百万个候选输入进行哈希并比较。对于低熵输入(短字符串、常见密码、顺序数字),预计算的彩虹表使这在实践中可行。对于高熵输入(随机 UUID、大文件),逆向在计算上不可行。这就是为什么单独使用 SHA 不适合存储密码 —— 你需要一个慢速、加盐的 KDF。

什么时候应该用 SHA-3 而不是 SHA-2?

SHA-3 适用于以下情况:(a)你希望使用来自不同设计谱系的哈希,以防未来 SHA-2 出现弱点;(b)你的协议要求在不使用 HMAC 的情况下免疫长度扩展攻击;(c)你在实现内部使用 SHA-3 的后量子签名方案;(d)你有 Keccak 硬件加速并需要吞吐量。对于大多数日常使用场景(TLS、JWT、校验和),SHA-256 有更广泛的生态系统支持,是务实的默认选择。SHA-3 在相同输出大小下并不比 SHA-2 更安全 —— 它是对长期安全性的一个不同赌注。

Ethereum 为什么使用 Keccak-256 而不是 NIST SHA-3?

Ethereum 设计于 2013–2014 年,早于 NIST 发布 FIPS 202(2015 年 8 月)最终确定 SHA-3 标准之前。当时,Keccak 提交被认为是可能的胜者,Ethereum 的作者直接采用了它。当 NIST 最终确定标准时,他们将域分隔填充从 0x01(原始 Keccak)改为 0x06,对相同输入产生不同输出。Ethereum 已经使用原始 Keccak 填充部署,无法更改。因此,“Ethereum keccak256”和”NIST SHA3-256”尽管共用相同的底层 Keccak-f 置换,却是不同的算法。


试用工具:SHA-1 · SHA-256 · SHA-384 · SHA-512 · SHA-3 —— 全部在浏览器中运行,数据不会离开你的设备。

标签: hash sha cryptography security