正在加载,请稍候…

什么是 SHA-256?哈希函数的工作原理及其应用场景

了解 SHA-256 是什么,加密哈希函数如何工作,为什么 SHA-256 被认为是安全的,以及它在 TLS、比特币、Git 和密码存储中的应用。

什么是 SHA-256?哈希函数的工作原理及其应用场景

什么是 SHA-256?

SHA-256(安全哈希算法 256 位)接受任意输入,并产生一个固定的 256 位(64 个十六进制字符)输出,称为摘要或哈希。

SHA-256("hello")     = 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
SHA-256("Hello")     = 185f8db32921bd46d35b2e4234ac97a7c3a2d08d3ef5a28c3a6c4e9c8e2e6dd5
SHA-256("hello!")    = (完全不同的 64 字符哈希)
SHA-256(1GB 文件)    = (仍然恰好 64 个字符)

什么是 SHA-256?哈希函数的工作原理及其应用场景 插图

SHA-256 的特性

确定性: 相同输入始终产生相同哈希。

单向性: 给定哈希,无法计算出原始输入。没有逆向算法——只能暴力破解。

雪崩效应: 改变输入的一个比特会完全改变输出。"hello" 和 "hello1" 产生完全无关的哈希。

抗碰撞性: 从未发现两个不同输入产生相同的 SHA-256 哈希。(MD5 和 SHA-1 存在已知碰撞攻击。)

快速: 现代 GPU 上每秒约 100 亿次哈希。非常适合文件完整性验证。对于密码来说很糟糕(见下文)。

什么是 SHA-256?哈希函数的工作原理及其应用场景 插图

SHA-256 的应用场景

TLS/HTTPS: 每个 HTTPS 证书都使用 SHA-256 签名。TLS 握手使用它进行密钥派生。

比特币: 工作量证明需要找到一个 nonce,使得 SHA-256(SHA-256(block_header)) 以足够多的零比特开头。比特币地址也源自 SHA-256。

Git: 每个提交都由其 SHA 哈希标识。更改提交内容的任何字节都会得到完全不同的哈希。

git log --oneline  # 显示提交哈希
git show abc1234   # 通过哈希前缀引用提交

文件完整性: 软件下载包含 SHA-256 校验和,以便验证文件未被损坏或篡改。

sha256sum ubuntu-24.04.iso
# 将输出与下载页面上的官方校验和进行比较

HMAC 签名: SHA-256 用于 HMAC 中对 API 请求和 webhook 进行签名。

crypto.createHmac('sha256', secret).update(payload).digest('hex');

什么是 SHA-256?哈希函数的工作原理及其应用场景 插图

SHA-256 与 MD5 及其他哈希的比较

哈希 输出 被破解? 速度 用途
MD5 128 位 是(碰撞) 非常快 仅用于遗留校验和
SHA-1 160 位 是(碰撞) 遗留(Git 正在迁移)
SHA-256 256 位 通用
SHA-512 512 位 在 64 位上更快 额外安全余量
SHA-3 可变 中等 替代设计

为什么 SHA-256 不适合密码

SHA-256 在 GPU 上每秒计算约 100 亿次哈希。攻击者利用泄露的数据库可以在数小时内破解 8 位字母数字密码。

应使用专为密码设计的慢速算法:

# 错误:使用 SHA-256 存储密码
import hashlib
password_hash = hashlib.sha256(password.encode()).hexdigest()  # 永远不要这样做

# 正确:使用 bcrypt(故意慢速)
import bcrypt
hashed = bcrypt.hashpw(password.encode(), bcrypt.gensalt(rounds=12))
# bcrypt 在 rounds=12 时 ≈ 330 哈希/秒,而 SHA-256 为 100 亿哈希/秒
# 抗破解能力相差 3000 万倍

计算 SHA-256

// Node.js
const hash = require('crypto').createHash('sha256').update('hello').digest('hex');
// '2cf24dba...'

// 流式处理大文件
const stream = require('fs').createReadStream('large-file.bin');
const hash = require('crypto').createHash('sha256');
stream.pipe(hash).on('finish', () => console.log(hash.digest('hex')));
import hashlib
hashlib.sha256(b'hello').hexdigest()
# '2cf24dba...'

# 文件哈希
with open('file.bin', 'rb') as f:
    h = hashlib.file_digest(f, 'sha256')
    print(h.hexdigest())

→ 在浏览器中使用 Hash Text Tool 对文本进行 SHA-256 及其他算法的哈希计算。