前置知识: 网络安全

哈希算法

5 minIntermediate2026/6/14

哈希算法原理:SHA-1/SHA-2/SHA-3/MD5/Bcrypt 等算法详解与应用场景。

1. 哈希算法基础

1.1 基本概念

哈希函数将任意长度输入映射为固定长度输出:

H:{0,1}{0,1}nH: \{0,1\}^* \rightarrow \{0,1\}^n

1.2 安全性质

性质描述
抗碰撞性找到 xyx \neq y 使 H(x)=H(y)H(x) = H(y) 在计算上不可行
抗原像性给定 hh,找到 xx 使 H(x)=hH(x) = h 在计算上不可行
抗第二原像性给定 xx,找到 yxy \neq x 使 H(y)=H(x)H(y) = H(x) 在计算上不可行
雪崩效应输入微小变化导致输出巨大变化

1.3 Merkle-Damgård 结构

大多数哈希算法采用此结构:

消息 → 填充 → 分块 → IV → [压缩函数] → [压缩函数] → ... → 哈希值

2. MD5 算法

2.1 概述

参数
输出长度128 位
分组长度512 位
轮数64(4×16)
安全性已破解

2.2 已知攻击

攻击年份描述
碰撞攻击2004王小云团队找到实际碰撞
选择前缀碰撞2006可构造有意义的碰撞文件
MD5 碰撞证书2008伪造 CA 证书

2.3 当前状态

禁止用于安全场景,仅可用于非安全目的(如文件校验、ETag)。

3. SHA-1 算法

3.1 概述

参数
输出长度160 位
分组长度512 位
轮数80
安全性已破解

3.2 SHAttered 攻击(2017)

Google 与 CWI 研究所成功找到 SHA-1 碰撞,计算代价约 2632^{63} 次。

禁止用于安全场景

4. SHA-2 家族

4.1 概述

算法输出长度安全等级
SHA-224224 位112 位
SHA-256256 位128 位
SHA-384384 位192 位
SHA-512512 位256 位

4.2 SHA-256 算法流程

  1. 消息填充(添加 1 位 + 零 + 64 位长度)
  2. 分成 512 位分组
  3. 每个分组进行 64 轮运算
  4. 每轮使用:消息调度字、轮常数、位运算(AND、XOR、ROT)

4.3 代码示例

import hashlib

# SHA-256
hash_sha256 = hashlib.sha256(b"Hello World").hexdigest()
# a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e

# SHA-512
hash_sha512 = hashlib.sha512(b"Hello World").hexdigest()

# HMAC
import hmac
hmac_sha256 = hmac.new(key, message, hashlib.sha256).hexdigest()

4.4 长度扩展攻击

Merkle-Damgård 结构的弱点:已知 H(m)H(m)mm 的长度,可以计算 H(mpaddingm)H(m || padding || m') 而不知道 mm

防御:使用 HMAC 而非直接哈希。

5. SHA-3(Keccak)

5.1 概述

算法输出长度特点
SHA3-224224 位海绵结构
SHA3-256256 位海绵结构
SHA3-384384 位海绵结构
SHA3-512512 位海绵结构
SHAKE128可变XOF
SHAKE256可变XOF

5.2 海绵结构

吸收阶段:消息分块 XOR 到状态中,经过置换函数
挤出阶段:从状态中提取输出

优势

  • 不受长度扩展攻击影响
  • 可扩展输出长度(XOF)
  • 与 SHA-2 完全不同的结构

6. 密码存储专用哈希

6.1 为什么不能用普通哈希

攻击描述
彩虹表预计算哈希值对照表
暴力破解GPU 每秒可计算数十亿次 SHA-256
字典攻击常见密码列表

6.2 Bcrypt

import bcrypt

# 哈希密码
hashed = bcrypt.hashpw(password.encode(), bcrypt.gensalt(rounds=12))

# 验证
bcrypt.checkpw(password.encode(), hashed)
参数
输出长度184 位
内置盐
自适应rounds 参数(默认 12)
最大密码长度72 字节

6.3 Argon2

from argon2 import PasswordHasher

ph = PasswordHasher()
hash = ph.hash("password")
ph.verify(hash, "password")
参数描述
时间成本迭代次数
内存成本内存使用量(MB)
并行度线程数

Argon2 优势:抗 GPU/ASIC 攻击,2015 年密码哈希竞赛冠军。

6.4 PBKDF2

import hashlib
import os

key = hashlib.pbkdf2_hmac('sha256', password.encode(), salt, 600000, dklen=32)
参数推荐值
迭代次数600,000+(SHA-256)
盐长度16+ 字节
输出长度32+ 字节

7. 应用场景与算法选择

场景推荐算法
密码存储Argon2id > Bcrypt > PBKDF2
数据完整性SHA-256 / SHA-3
数字签名SHA-256 / SHA-384
文件校验SHA-256
HMACHMAC-SHA256
禁止使用MD5、SHA-1(安全场景)