SHA-256 算法详解
概述
简介
SHA-256(Secure Hash Algorithm 256-bit)是一种密码学哈希函数,由美国国家安全局(NSA)设计,并由美国国家标准与技术研究院(NIST)发布。SHA-256 属于 SHA-2 系列哈希函数,生成一个固定长度为 256 位(32 字节) 的哈希值。
主要特点
| 特性 | 说明 |
|---|---|
| 输出长度 | 256 位(32 字节) |
| 块大小 | 512 位(64 字节) |
| 轮数 | 64 轮 |
| 安全性 | 抗碰撞、抗原像攻击 |
算法步骤
1. 预处理(Preprocessing)
1.1 填充消息(Padding the Message)
填充规则
SHA-256 处理的消息长度必须是 512 位(64 字节) 的倍数。
填充步骤:
- 在消息末尾添加一个
1比特 - 添加
0比特,直到消息长度模 512 等于 448 - 添加一个 64 位的消息长度表示(未填充前的长度)
填充示例
如果消息长度是 128 比特(16 字节),则需要填充 320 个
0比特和 64 位的长度信息,总共 位。
1.2 划分消息块
将填充后的消息划分为 512 位(64 字节) 长度的块。
2. 初始化哈希值
八个初始哈希值
SHA-256 使用八个 32 位的初始哈希值(取自前 8 个质数平方根的小数部分):
H0 = 0x6a09e667
H1 = 0xbb67ae85
H2 = 0x3c6ef372
H3 = 0xa54ff53a
H4 = 0x510e527f
H5 = 0x9b05688c
H6 = 0x1f83d9ab
H7 = 0x5be0cd19
3. 处理消息块
3.1 轮常量(Round Constants)
使用 64 个 32 位常量(取自前 64 个质数立方根的小数部分):
K = [0x428a2f98, 0x71374491, ..., 0xc67178f2]
3.2 消息调度(Message Schedule)
对于每个 512 位的消息块 M(i),扩展成 64 个 32 位字 W[0..63]:
扩展规则
- 对于 到 :
W[t] = M(i)[t]- 对于 到 :
s0 = (W[t-15] rightrotate 7) ^ (W[t-15] rightrotate 18) ^ (W[t-15] >> 3)
s1 = (W[t-2] rightrotate 17) ^ (W[t-2] rightrotate 19) ^ (W[t-2] >> 10)
W[t] = W[t-16] + s0 + W[t-7] + s1
3.3 压缩函数(Compression Function)
初始化工作变量:
a = H0 b = H1 c = H2 d = H3
e = H4 f = H5 g = H6 h = H7
64 轮迭代: 对于 到 :
S1 = (e rightrotate 6) ^ (e rightrotate 11) ^ (e rightrotate 25)
ch = (e & f) ^ ((~e) & g)
temp1 = h + S1 + ch + K[t] + W[t]
S0 = (a rightrotate 2) ^ (a rightrotate 13) ^ (a rightrotate 22)
maj = (a & b) ^ (a & c) ^ (b & c)
temp2 = S0 + maj
h = g g = f f = e e = d + temp1
d = c c = b b = a a = temp1 + temp2
更新哈希值:
H0 = H0 + a H1 = H1 + b H2 = H2 + c H3 = H3 + d
H4 = H4 + e H5 = H5 + f H6 = H6 + g H7 = H7 + h
4. 生成最终哈希值
结果
连接
H0 || H1 || H2 || H3 || H4 || H5 || H6 || H7得到最终的 256 位哈希值。
代码实现
Go 语言示例
package main
import (
"crypto/sha256"
"encoding/hex"
"fmt"
)
func main() {
input := "example string"
hash := sha256.New()
hash.Write([]byte(input))
hashedBytes := hash.Sum(nil)
hashString := hex.EncodeToString(hashedBytes)
fmt.Printf("Input: %s\nHash: %s\n", input, hashString)
}冲突概率分析
理论基础
什么是哈希冲突?
哈希冲突是指两个不同的输入数据生成了相同的哈希值。
SHA-256 的输出空间为 (约 ),因此冲突概率极低。
生日悖论
根据生日悖论,要达到 50% 冲突概率所需的输入数目约为 。
冲突概率表
| 输入数量 | 冲突概率 |
|---|---|
| 1 亿() | |
| 1 万亿() | |
实际应用
在实际应用中,几乎不可能碰到 SHA-256 哈希冲突。
冲突概率可视化
绘图代码
图表说明
- X 轴:输入数量(对数刻度)
- Y 轴:冲突概率(对数刻度)
- 红色虚线:概率 = 1 的参考线
总结
核心要点
- SHA-256 生成 256 位固定长度哈希值
- 冲突概率极低,在实际应用中可忽略不计
- 广泛应用于:
- 数据完整性校验
- 密码存储
- 数字签名
- 区块链技术
相关链接
- MD5 - 较早的哈希算法(已不安全)
- SHA-1 - SHA-256 的前身(已不推荐使用)
- SHA-512 - SHA-2 系列中更长的变体
- HMAC - 基于哈希的消息认证码
- 数字签名 - SHA-256 的重要应用场景
参考资料
- NIST FIPS 180-4 - SHA 标准规范
- RFC 6234 - SHA-256 实现指南