文件哈希校验:MD5/SHA256
下载文件被篡改、传输过程出错、确保文件完整性——哈希校验是基础工具。本文详解 MD5/SHA256 等。
什么是哈希?
哈希(Hash)是把任意长度数据映射为固定长度字符串的函数:
输入:Hello, World!
MD5:6cd3556deb0da54bca060b4c39479839
SHA256:dffd6021bb2bd5b0af676290809ec3a53191a81...
特性
- 定长输出:无论输入多长,输出固定长度
- 单向:从哈希反推原数据不可能
- 唯一性:相同输入永远相同输出
- 雪崩效应:输入微小变化,输出完全不同
用途
- 文件完整性校验
- 密码存储
- 数字签名
- 数据去重
- 负载均衡(一致性哈希)
常见哈希算法
MD5
- 输出:128 位(32 位十六进制)
- 速度快
- 不安全:已发现碰撞,不能用于安全场景
- 用途:非安全场景的校验
SHA-1
- 输出:160 位(40 位十六进制)
- 速度中等
- 不安全:2017 年 Google 公开碰撞
- 用途:已被弃用
SHA-256
- 输出:256 位(64 位十六进制)
- 速度慢
- 安全:截至 2026 年无实际攻击
- 用途:主流安全场景
SHA-3
- 输出:可变
- 新一代标准
- 安全性高
- 用得少
BLAKE2/3
- 比 SHA-2 快
- 安全性高
- 现代选择
52tool 哈希工具
工具地址:哈希计算
功能
- MD5、SHA-1、SHA-256、SHA-512
- 文件哈希
- 文本哈希
- HMAC(带密钥哈希)
- 浏览器端处理
实战 1:文件哈希
上传文件 report.pdf:
MD5:a3f5b8c1d2e4f6a7b9c8d0e1f2a3b4c5
SHA-1:b89ea7c5d4f3a2b1c0d9e8f7a6b5c4d3e2f1a0b9
SHA-256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4...
实战 2:文本哈希
输入:
Hello, World!
输出:
MD5:6cd3556deb0da54bca060b4c39479839
SHA-256:dffd6021bb2bd5b0af676290809ec3a53191a8111c...
实战 3:HMAC
输入:
消息:Hello
密钥:secret
算法:HMAC-SHA256
输出:
HMAC:8c54e8e2a4c81e2b8b4b6d1f3a5e7c9d...
文件完整性校验
校验流程
- 文件提供方计算哈希(如 SHA-256)
- 公布哈希值
- 下载方下载文件
- 重新计算哈希
- 对比哈希,一致则文件完整
实战:校验下载文件
Linux ISO 下载:
提供方:
ubuntu-24.04.iso
SHA256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4...
下载方:
$ sha256sum ubuntu-24.04.iso
e3b0c44298fc1c149afbf4c8996fb92427ae41e4... ubuntu-24.04.iso
哈希一致,文件未篡改。
工具
Windows:
Get-FileHash file.zip -Algorithm SHA256
或用 52tool 哈希工具上传文件计算。
Linux/Mac:
md5sum file.zip
sha1sum file.zip
sha256sum file.zip
编程实现
JavaScript
// 文本哈希
async function hashText(text, algorithm = 'SHA-256') {
const buffer = new TextEncoder().encode(text);
const hash = await crypto.subtle.digest(algorithm, buffer);
return Array.from(new Uint8Array(hash))
.map(b => b.toString(16).padStart(2, '0'))
.join('');
}
await hashText('Hello'); // SHA-256 哈希
// 文件哈希
async function hashFile(file, algorithm = 'SHA-256') {
const buffer = await file.arrayBuffer();
const hash = await crypto.subtle.digest(algorithm, buffer);
return Array.from(new Uint8Array(hash))
.map(b => b.toString(16).padStart(2, '0'))
.join('');
}
Python
import hashlib
# 文本
hash_md5 = hashlib.md5(b'Hello').hexdigest()
hash_sha256 = hashlib.sha256(b'Hello').hexdigest()
# 文件
def hash_file(path, algorithm='sha256'):
h = hashlib.new(algorithm)
with open(path, 'rb') as f:
while chunk := f.read(8192):
h.update(chunk)
return h.hexdigest()
# HMAC
import hmac
h = hmac.new(b'secret', b'Hello', hashlib.sha256).hexdigest()
命令行
# 文本
echo -n "Hello" | md5sum
echo -n "Hello" | sha256sum
# 文件
md5sum file.zip
sha256sum file.zip
Java
import java.security.MessageDigest;
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] hash = md.digest("Hello".getBytes());
StringBuilder sb = new StringBuilder();
for (byte b : hash) {
sb.append(String.format("%02x", b));
}
String hexHash = sb.toString();
实战场景
场景 1:校验下载文件
1. 从官网下载 ISO 文件
2. 官网提供 SHA256 校验值
3. 本地 sha256sum 计算
4. 对比,一致则文件未被篡改
场景 2:密码存储
import hashlib, os
def hash_password(password):
salt = os.urandom(32)
hash = hashlib.pbkdf2_hmac('sha256', password.encode(), salt, 100000)
return salt + hash
def verify_password(password, stored):
salt = stored[:32]
hash = stored[32:]
new_hash = hashlib.pbkdf2_hmac('sha256', password.encode(), salt, 100000)
return new_hash == hash
不要直接 SHA256 密码,要用 PBKDF2/bcrypt/Argon2 等慢哈希。
场景 3:文件去重
# 计算每个文件哈希
hashes = {}
for file in files:
h = hash_file(file)
if h in hashes:
print(f'{file} 与 {hashes[h]} 相同')
else:
hashes[h] = file
场景 4:API 签名
import hmac, hashlib
def sign_request(params, secret):
message = '&'.join(f'{k}={v}' for k, v in sorted(params.items()))
signature = hmac.new(secret.encode(), message.encode(), hashlib.sha256).hexdigest()
return signature
场景 5:Git 提交哈希
Git 用 SHA-1 标识提交。每次 commit 生成唯一哈希:
commit a3f5b8c1d2e4f6a7b9c8d0e1f2a3b4c5d6e7f8a9
参考 52tool 哈希工具 验证 Git commit 完整性。
场景 6:区块链
区块链用 SHA-256 链接区块:
区块 N 哈希 = SHA256(区块 N 内容 + 区块 N-1 哈希)
篡改任何区块都会导致后续哈希变化。
哈希碰撞
什么是碰撞?
两个不同输入产生相同哈希:
输入 1 → 哈希 X
输入 2 → 哈希 X
MD5 碰撞
2004 年王小云团队发现 MD5 碰撞,能在数小时内生成两个不同文件有相同 MD5。
SHA-1 碰撞
2017 年 Google 公开 SHA-1 碰撞,SHAttered 攻击。
SHA-256 安全
截至 2026 年无已知实际攻击,仍是安全选择。
碰撞的影响
- 文件校验:可能被恶意篡改(替换文件但哈希相同)
- 数字签名:签名可能被伪造
- 密码存储:理论上可能但实际不可行
慢哈希 vs 快哈希
快哈希
MD5、SHA-256:每秒计算百万次。适合文件校验,不适合密码存储(暴力破解快)。
慢哈希
bcrypt、PBKDF2、Argon2:故意慢(每次 100ms+),暴力破解成本极高。用于密码存储。
加盐
为什么加盐?
不加盐:相同密码哈希相同,彩虹表攻击可行。
密码 "123456" → 哈希 X
所有用户用 "123456" 都得到哈希 X
攻击者查彩虹表得到原密码
加盐
用户 A:密码 "123456" + 盐 "abc" → 哈希 Y
用户 B:密码 "123456" + 盐 "xyz" → 哈希 Z
不同用户相同密码哈希不同。
实践
import hashlib, os
salt = os.urandom(32) # 每个用户不同
hash = hashlib.pbkdf2_hmac('sha256', password.encode(), salt, 100000)
常见问题
Q: MD5 还能用吗?
A: 非安全场景能用(如文件去重、缓存键)。安全场景(密码、签名)不能用。
Q: SHA-1 还能用吗?
A: 不建议。已被弃用,用 SHA-256。
Q: 怎么存密码?
A: 用 bcrypt、PBKDF2、Argon2 等慢哈希 + 加盐。不要直接 SHA256。
Q: 哈希能反推原数据吗?
A: 不能。哈希是单向函数。
Q: 怎么验证文件完整性?
A: 计算文件 SHA-256,与官方提供的哈希对比。一致则未篡改。
Q: 工具会泄露我的文件吗?
A: 52tool 哈希工具在浏览器端运行,文件不上传服务器。适合处理敏感文件。
常见问题解答
Q: 怎么计算文件 SHA256?
A: Windows: Get-FileHash file.zip -Algorithm SHA256。Linux: sha256sum file.zip。或用 52tool 哈希工具 上传文件计算。
Q: MD5 和 SHA256 哪个好?
A: SHA256。MD5 已被破解,不安全。文件校验也建议用 SHA256。
Q: 怎么验证下载文件?
A: 1) 下载文件;2) 计算本地 SHA256;3) 与官方哈希对比;4) 一致则文件完整。
Q: 密码能直接 SHA256 存吗?
A: 不能。直接 SHA256 易被彩虹表攻击。用 PBKDF2/bcrypt/Argon2 加盐慢哈希。
Q: 哈希碰撞是什么?
A: 两个不同输入产生相同哈希。MD5 和 SHA1 已被破解(可人为制造碰撞),SHA256 安全。
Q: HMAC 和普通哈希区别?
A: HMAC 是带密钥的哈希(Hash-based MAC),用于消息认证。普通哈希无密钥,任何人可计算。
总结
哈希是数据完整性的基石:
- 文件校验 → 52tool 哈希工具
- 推荐 SHA-256
- 密码存储 → bcrypt/PBKDF2 + 加盐
- 文件去重 → MD5 即可
记住:MD5 不用于安全,密码用慢哈希加盐,SHA-256 是安全默认。