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. 在消息末尾添加一个 1 比特
  2. 添加 0 比特,直到消息长度模 512 等于 448
  3. 添加一个 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 的参考线

总结

核心要点

  1. SHA-256 生成 256 位固定长度哈希值
  2. 冲突概率极低,在实际应用中可忽略不计
  3. 广泛应用于:
    • 数据完整性校验
    • 密码存储
    • 数字签名
    • 区块链技术

相关链接

  • MD5 - 较早的哈希算法(已不安全)
  • SHA-1 - SHA-256 的前身(已不推荐使用)
  • SHA-512 - SHA-2 系列中更长的变体
  • HMAC - 基于哈希的消息认证码
  • 数字签名 - SHA-256 的重要应用场景

参考资料