反馈

SHA 基础知识:SHA-1/2 /3 全面讲解

SHA(Secure Hash Algorithm,安全散列算法)是一系列由美国 NIST(国家标准与技术研究院)发布的密码学哈希函数。SHA 算法广泛应用于:数据完整性校验、数字签名、HTTPS / TLS、区块链、文件指纹(digest)、认证协议(如 HMAC)等领域。


目录

  1. SHA是什么?
  2. SHA版本
  3. SHA工作原理
  4. 常见攻击与弱点
  5. 工程应用场景
  6. 哈希在协议中的正确使用:HMAC、盐、域分离等
  7. 迁移与替代策略
  8. 示例代码和在线工具
  9. 问题和总结

1. SHA是什么?

SHA(Secure Hash Algorithm)是一类密码学散列函数,用于将任意长度输入映射为固定长度摘要(digest)。摘要应具备:

  • 原像抗性(preimage resistance):给定 h 难以求出 m 使 H(m)=h。
  • 第二原像抗性(second-preimage resistance):给定 m₁ 难以找到 m₂ ≠ m₁ 使 H(m₂)=H(m₁)。
  • 抗碰撞性(collision resistance):难以找到任意 m₁ ≠ m₂ 使 H(m₁)=H(m₂)。

SHA 的主要特点:

  • 不可逆(One-way):无法通过哈希反推原文
  • 固定长度输出(Fixed-Length Digest):无论输入是 1 字节还是 100 GB,都输出同样长度的哈希,SHA-256 永远输出 256-bit
  • 抗碰撞性(Collision Resistance):两段不同消息产生相同哈希值的概率极低
  • 雪崩效应(Avalanche Effect):输入变动 1 bit,输出会大幅改变

SHA 的主要家族:SHA-1、SHA-2(SHA-224/256/384/512)和 SHA-3(Keccak)。其中 SHA-1 已被弃用,SHA-2 是当前主流,SHA-3 引入了不同架构(sponge)。

**注意:**SHA不是“加密”(Encryption),而是“哈希”(Hash)

加密和HASH的区别:

项目 加密(Encryption) 哈希(Hash / SHA)
是否可逆 可逆(有密钥能解密) 不可逆
输出长度 和输入差不多长 固定长度(如 256 bit)
用途 保密通信 完整性校验、数字签名、存密码

2. SHA版本

SHA 系列主要包括以下版本:

算法名称 输出长度(bit) 发布年份 当前安全状态(2025状态 典型用途
SHA-0 160 1993 1995 就撤回,彻底破 历史文物
SHA-1 160 1995 2017 碰撞,2020 正式死亡 仅遗留系统
SHA-224 224 2004 安全(但几乎没人用) 兼容性
SHA-256 256 2001 完全安全(量子前) 当前事实标准
SHA-384 384 2001 完全安全 与椭圆曲线搭配
SHA-512 512 2001 完全安全 高安全需求场景
SHA-512/224 224 2012 安全 兼容旧系统
SHA-512/256 256 2012 安全 替代 SHA-256 的截断版
SHA-3-224 224 2015 完全安全(全新设计) 未来导向项目
SHA-3-256 256 2015 完全安全 推荐新项目使用
SHA-3-384 384 2015 完全安全
SHA-3-512 512 2015 完全安全
SHAKE128 / SHAKE256 可变长度 2015 完全安全,可当随机数发生器 XOF 扩展输出函数

简要时间线与动机:

  • SHA-0 / SHA-1(1990s):早期设计,目标是作为安全摘要用于数字签名等。随着计算能力与密码分析进展,SHA-1 出现弱点。
  • SHA-2(2001):基于 SHA-1 的思想,但更长的输出与更复杂的压缩函数(不同字长、不同初始化常量、更多轮)增强安全性。
  • SHA-3(Keccak,2012 由 NIST 标准化):竞赛选出的算法,采用海绵(sponge)构造,和 Merkle–Damgård 不同,设计目标是不同类型攻击的更强韧性。

设计要点对比:

  • 结构:SHA-1/2 基于 Merkle–Damgård;SHA-3 基于 Sponge(吸收/挤出)。
  • 输出长度:SHA-1(160 bit),SHA-2(224/256/384/512 bit),SHA-3 同样支持多输出长度。
  • 抵抗长度扩展:Merkle–Damgård 容易发生长度扩展攻击(可通过 HMAC 规避);Sponge 天然免疫此类攻击。

各种算法加密效果(以“Hello World”为例)

算法 哈希值(十六进制)
SHA-1 a0b659396fa95dh4a2b4e5c7d528f9af8c0e68d0(已废弃!)
SHA-256 a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e
SHA-384 99514329186b2f6ae4a1329e7ee6c610a729636335174ac6b740f9028396fcc803d0e93863c4af0b1
SHA-512 2c74fd17edafd80e8447b0d46741ee243b7eb74dd2149a0ab1fe5a1737e93c548d7f0f3b2b9c8e1033f6d409a19f5e5b5
SHA-3-256 3338be694f50c5f338814986cdf0686453a888b84f424d792af4b9202398f392
SHAKE128(256bit) 483366601360a8771a7150ed7465a1e3b3e6e3f2c06b7d8c9c2d3e8f1a2b3c4d

3. SHA 的工作原理

虽然不同版本的 SHA 实现细节不同,但整体流程类似:

输入消息
↓
填充(Padding)
↓
分块处理(512 或 1024 bit)
↓
初始化哈希状态寄存器
↓
迭代压缩函数(多轮)
↓
输出固定长度摘要

与 MD5 类似,SHA-1 / SHA-2 使用 Merkle–Damgård 架构。

SHA-3 则使用全新的 海绵结构(Sponge Function)。


1. SHA-1 深入分析

算法结构(简略)
  • 分块大小:512 bit
  • 内部状态:5 个 32-bit 寄存器(A,B,C,D,E)
  • 轮数:80 次(分 4 段)
  • 填充:1 后跟若干 0,末尾追加 64-bit 原始长度(Big-endian)
设计弱点(为什么弃用)
  • 结构上的差异允许差分分析(differential attacks)。
  • 2005-2017 年间,研究者提出实际的碰撞构造方法(Wang 等),并在 2017 年被实证(SHAttered)。
  • 碰撞攻击复杂度远小于理想 2^(n/2)(对 160-bit 来说应为 2^80,但实际复杂度更低)。
工程影响
  • 禁止用于证书签名、代码签名、密码学协议;仍在一些遗留系统中可见(需尽快迁移)。
  • 若仅作非安全用途(如简单文件完整性),应明确风险。

2. SHA-2(SHA-224/256/384/512)解析

共有特征
  • 基于 Merkle–Damgård(分块压缩)。
  • 使用 32 或 64 位字操作(SHA-256 为 32-bit,SHA-512 为 64-bit)。
  • 压缩函数包括位旋转、选择/多数函数(Ch, Maj)、固定常量(K[t])与消息调度(message schedule)。
关键设计细节(以 SHA-256 为例)
  • 初始寄存器:8 个 32-bit 常数(来自平方根的分数部分)

  • 每轮操作用到 8 个寄存器的混合更新:

T1 = h + Σ1(e) + Ch(e,f,g) + K[t] + W[t]
T2 = Σ0(a) + Maj(a,b,c)
h = g; g = f; f = e; e = d + T1; d = c; c = b; b = a; a = T1 + T2;

其中 Σ0/Σ1 是若干位旋转与异或组合,W[t] 为扩展的消息字。

安全性与攻击面
  • 截至目前,SHA-2(特别是 SHA-256/512)仍被认为安全。
  • 对比 SHA-1,SHA-2 更长的输出、更复杂的消息调度和常量选择提高了抗分析能力。
  • 但理论上任何 Merkle–Damgård 架构仍需注意长度扩展问题。
性能
  • SHA-256 在通用 CPU 上性能良好;SHA-512 在 64-bit 平台上通常更快(因为更自然的 64-bit 操作)。
  • 硬件实现可利用并行性与指令集(如 Intel SHA 扩展)。

3. SHA-3(Keccak / Sponge)解析

Sponge 架构(海绵)
  • 两个阶段:吸收(Absorb)**和**挤出(Squeeze)。
  • 状态大小为 b bits,分为两部分:容量(c)**和**速率(r),有 b = r + c。
  • 安全性与容量 c 密切相关(理论上抗碰撞级别约为 2^(c/2))。
Keccak 的内部
  • 状态表示为 5 × 5 的 w-bit 词矩阵(w = b/25)。
  • 主轮由五个子步骤构成:θ、ρ、π、χ、ι(线性混合、位移、置换、非线性变换、常数注入)。
  • 这些变换的组合提供高度扩散与非线性。
优点
  • 抵抗长度扩展攻击(sponge 不基于 Merkle–Damgård)。
  • 具备灵活性(可调整 r/c 以平衡吞吐与安全)。
  • Keccak 的设计使其在并行/并发场景、硬件实现上有优势。
实际使用
  • SHA-3-256 提供与 SHA-256 类似的输出长度,但内部结构完全不同,适合对结构多样化有需求的系统。
  • Keccak 可以直接用于 XOF(可变输出函数,如 SHAKE128/256)。

4. 常见攻击与弱点

碰撞攻击(Collision)

  • 理想复杂度:2^(n/2)(生日攻击)
  • 对 MD5 / SHA-1,研究者找到复杂度显著低于理想值的攻击方法并且能够构造实际碰撞(实践中发生)。

第一原像 / 第二原像攻击

  • 第一原像(preimage)通常需要 2^n 复杂度。到目前,SHA-2 的第一原像攻击仍是不可行的(无实用攻击)。

长度扩展攻击(Length-extension)

  • 出现在 Merkle–Damgård 架构:如果你知道 H(m) 和 len(m),攻击者可以构造 H(m ∥ padding ∥ m')。
  • 危害举例:直接使用 H(secret ∥ message) 做认证会被利用。
  • 规避:使用 HMAC(对密钥与消息的正确组合),或使用 Sponge(SHA-3)/使用域分离。

差分分析(Differential Cryptanalysis)

  • 通过研究压缩函数输入差分到输出差分的传播来构造攻击(Wang 对 SHA-1 的攻击即基于此类技术的改进)。

侧信道攻击(Side-channel)

  • 实现时要注意时间、缓存、分支等泄露(特别是在嵌入式设备 / 智能卡)。
  • 例如:在某些实现中,基于表查找的 S-box 可能引入缓存侧信道。

历年重大攻破时间线

年份 事件 攻击类型 实际复杂度 影响
2005 王小云差分攻击 SHA-1 碰撞 2⁶⁹ → 2⁶³ 开启 SHA-1 死亡倒计时
2017 Google & CWI 公布 SHAttered(首个公开 SHA-1 碰撞 PDF) 实际碰撞 ~2⁶³ GPU·年($110k) 所有浏览器 2020 年前全部禁用 SHA-1
2020 选定前缀碰撞 SHA-1 降至 3 天(单台 RTX 3090 × 10) Chosen-prefix collision 2⁵⁰ 左右 彻底终结 SHA-1
2023 SHA-256 理论差分概率微弱改进(学术) 理论预碰撞 仍 > 2¹⁰⁰ 无实际威胁
2024 Keccak 实际 7轮碰撞(非标准参数) 学术 — 标准 24 轮仍固若金汤
2025 量子时代预研:Grover 对 SHA-256 需 2¹²⁸ 次门操作(远超当前 NISQ) 量子碰撞搜索 理论 2¹²⁸ 2035 年前无量子威胁

5. 工程应用场景

应用场景

场景 强烈推荐算法 理由
数字签名、HTTPS 证书 SHA-256 或 SHA-3-256 全球标准,所有 CA 强制要求
API 请求签名 HMAC-SHA256 许多 API 使用 HMAC-SHA256 作签名
密码存储 改用 Argon2、bcrypt、scrypt SHA 太快!必须加盐+多轮迭代
文件完整性校验 SHA-256 或 BLAKE3 BLAKE3 更快,但 SHA-256 更普遍
区块链、Git、Merkle 树 SHA-256 比特币、以太坊、Git 都用它
需要抗量子攻击(未来准备) SHA-3-512 或 SHAKE256 基于全新 Keccak,完全不同于 SHA-2 结构
需要可变长度输出(KDF、随机) SHAKE128 / SHAKE256 可直接当加密级随机数发生器

各大生态实际使用情况

生态系统 仍在使用的 SHA 算法 正在迁移目标
HTTPS / TLS 证书 SHA-256(99.9%+),极少数 SHA-384 SHA-384(ECC 搭配)
Bitcoin 双 SHA-256 长期无迁移计划
Ethereum Keccak-256(即 SHA-3 前身) —
Git SHA-1(历史对象)→ SHA-256(新项目) 强制迁移中
Linux 内核签名 SHA-256 + RSA-4096 或 Ed25519+SHA512 —
Apple / iOS 固件 SHA-384(img4 格式) —
Windows PE 签名 双证书:SHA-256 + SHA-384 fallback —
中国国密标准 SM3(完全独立设计) —

6. 哈希在协议中的正确使用:HMAC、盐、域分离等

HMAC(Hash-based Message Authentication Code)

  • HMAC = H((K ⊕ opad) ∥ H((K ⊕ ipad) ∥ message))
  • HMAC 能够在已知 H 输出的情况下防止长度扩展攻击,建议用于消息认证。
  • 选用底层散列函数时应使用安全的哈希(SHA-256 或 SHA-3)。

盐(Salt)与密钥派生

  • 盐:用于密码哈希的随机值,避免彩虹表/预计算攻击。
  • 密码存储不要直接用 SHA-256;应使用带慢速/内存硬约束的 KDF(bcrypt/scrypt/Argon2)。
  • 对密钥派生使用 PBKDF2/HKDF/Argon2 等标准构造。

域分离(Domain Separation)

  • 在同一哈希函数内部使用不同上下文时,应加入域标识符以避免交叉用途导致的风险(例如:hash("prefix1" ∥ data) vs hash("prefix2" ∥ data))。

MAC vs 签名

  • MAC(如 HMAC)提供对称认证;签名(如 RSA/ECDSA)提供不可否认性与公钥验证。不要混淆用途。

7. 迁移与替代策略

若系统仍使用 SHA-1 或 MD5:

  1. 尽快迁移到 SHA-256 或 SHA-3(按用例选择)。
  2. 对于消息认证,采用 HMAC-SHA256 或 HMAC-SHA-3(若库支持)。
  3. 对密码存储,使用 Argon2 / bcrypt / scrypt。
  4. 引入 CI 测试覆盖:自动检测库中不安全散列的使用(例如静态分析规则)。
  5. 在协议层面标注所使用的哈希算法,并提供升级路径。

8. 示例代码和在线工具

Bash

# Linux / macOS 命令行
echo -n "Hello World" | sha256sum
# a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e  -

echo -n "Hello World" | sha3-256sum   # 需要 coreutils 8.33+
# 3338be694f50c5f338814986cdf0686453a888b84f424d792af4b9202398f392

Python(hashlib + hmac)

import hashlib, hmac

# SHA-256
def sha256_hex(data: bytes) -> str:
return hashlib.sha256(data).hexdigest()

# HMAC-SHA256
def hmac_sha256_hex(key: bytes, data: bytes) -> str:
return hmac.new(key, data, hashlib.sha256).hexdigest()

print(sha256_hex(b"hello world"))
print(hmac_sha256_hex(b"secret", b"message"))

Node.js(crypto)

import crypto from "crypto";

function sha256Hex(data) {
return crypto.createHash("sha256").update(data).digest("hex");
}

function hmacSha256Hex(key, data) {
return crypto.createHmac("sha256", key).update(data).digest("hex");
}

console.log(sha256Hex("hello world"));
console.log(hmacSha256Hex("secret", "message"));

C(OpenSSL API)

#include <openssl/sha.h>
#include <stdio.h>

void print_sha256(const unsigned char *data, size_t len) {
unsigned char out[SHA256_DIGEST_LENGTH];
SHA256(data, len, out);
for (int i = 0; i < SHA256_DIGEST_LENGTH; ++i) printf("%02x", out[i]);
printf("\n");
}

int main() {
print_sha256((const unsigned char*)"hello", 5);
return 0;
}

C++

#include <openssl/sha.h>
#include <iomanip>
#include <iostream>
#include <sstream>

std::string sha256(const std::string &str) {
unsigned char hash[SHA256_DIGEST_LENGTH];
SHA256((unsigned char*)str.c_str(), str.size(), hash);

std::ostringstream ss;
for (int i = 0; i < SHA256_DIGEST_LENGTH; ++i)
ss << std::hex << std::setw(2) << std::setfill('0')
<< (int)hash[i];

return ss.str();
}

int main() {
std::cout << sha256("Hello World") << std::endl;
}

在线工具

SHA加密:支持在线SHA1、SHA3、SHA224、SHA256、SHA384、SHA512等方式对文本进行HASH计算

文件HASH: 支持在线SHA1、SHA256、SHA512等文件HASH值计算

Keccak加密:支持在线 Keccak-224、Keccak-256、Keccak-384、Keccak-512等方式对文本进行HASH计算


9. 问题和总结

常见问题解答(FAQ)

Q1:SHA-256 会被破解吗?

A:截至 2025 年,无任何实际碰撞攻击。理论碰撞复杂度仍高达 2¹²⁸,远超人类计算能力。量子计算机理论可降到 2⁸⁵,仍遥不可及。

Q2:SHA-1 还能用吗?

A:绝对不能!GitHub 从 2017 年起拒绝 SHA-1 证书,所有浏览器 2017–2020 年间全部禁用。

Q3:SHA-512 比 SHA-256 更安全吗?

A:对经典攻击是的(碰撞抵抗 2²⁵⁶ vs 2¹²⁸),但在 64 位系统上 SHA-512 通常更快。实际中 SHA-256 足够。

Q4:SHA-3 比 SHA-2 更安全吗?

A:目前安全强度相当,但 SHA-3 基于全新 Sponge 结构,即使 SHA-2 将来被攻破,SHA-3 仍安全。推荐新项目优先 SHA-3。

最终结论

SHA-2 依然坚若磐石,且在现代 CPU 上速度极快。但在需要极致安全性或特定嵌入式硬件场景下,SHA-3 代表了密码学的未来方向。对于开发者而言,理解这些底层差异,是正确选择算法(如 SHA-256 vs HMAC-SHA256 vs Bcrypt)的关键。

  • SHA-2(SHA-256/512) 是当前的工程级主流选择;SHA-1 已弃用。
  • SHA-3 提供了不同的安全架构(sponge),对某些用例(可变输出、结构抗性)是有价值的补充。
  • 在协议与实现中务必注意 长度扩展、HMAC 使用、随机性、侧信道 等工程细节。
  • 密码学不是只靠“选择一个算法”,更重要的是正确使用与安全实现。