哈希函数基础
目录
哈希函数概述
什么是哈希函数
哈希函数是一种数学函数,它将任意长度的输入数据(称为"消息")映射到固定长度的输出值(称为"哈希值"、"摘要"或"指纹")。
哈希函数的基本形式:
H: {任意长度的数据} → {固定长度的数据}
例如:
H("Bitcoin") = 一个256比特的固定长度输出
H("Bitcoin is a peer-to-peer electronic cash system") = 同样是256比特的输出哈希函数的直观理解
可以把哈希函数想象成一个"指纹机":
- 输入:一个人(代表任意长度的数据)
- 处理:提取生物特征
- 输出:一个唯一的指纹(固定长度的代表性数据)
即使两个人看起来非常相似,他们的指纹也会完全不同。同样,即使两个输入数据仅相差一个字符,生成的哈希值也会完全不同。
为什么比特币需要哈希函数
比特币系统依赖哈希函数来实现:
- 数据完整性验证:检测数据是否被篡改
- 交易验证:验证交易的合法性
- 区块链结构:链接不同的区块,形成不可篡改的链
- 挖矿工作:找到满足条件的哈希值
- 地址生成:从公钥生成比特币地址
- 默克尔树:聚合区块中的所有交易
哈希函数的性质
1. 确定性(Deterministic)
定义:相同的输入总是产生相同的输出。
H(x) = H(x) 对任何输入 x 总是成立
例如:
H("Bitcoin") 今天计算结果 = H("Bitcoin") 明天计算结果 = H("Bitcoin") 10年后计算结果为什么重要:确定性允许网络中的所有节点对相同数据进行哈希计算,得到相同结果,从而验证数据的一致性。
2. 快速计算(Efficient)
定义:哈希值可以快速计算,即使输入数据非常大。
计算速度示例:
- 计算 1 MB 数据的哈希值:毫秒级
- 计算 1 GB 数据的哈希值:秒级为什么重要:在比特币网络中,节点需要快速验证交易和区块。如果哈希计算很慢,整个网络的效率会大幅下降。
3. 单向性(One-Way)
定义:从哈希值反推原始输入在计算上是不可行的。
已知:H(x) = y
要求:找到 x
结论:在没有其他信息的情况下,计算上不可行为什么重要:
- 无法从比特币地址(哈希值)反推私钥(原始数据)
- 无法从交易的哈希值反推交易的具体内容
- 保证了比特币的安全性
4. 抗碰撞性(Collision Resistance)
定义:在实际中,不存在两个不同的输入产生相同的输出。
要求:找到 x1 ≠ x2 使得 H(x1) = H(x2)
对于安全的哈希函数:在实际中不可行为什么重要:
- 如果两个不同的交易产生相同的哈希值,就无法区分它们
- 如果两个不同的区块产生相同的哈希值,区块链就会混乱
- 抗碰撞性是区块链完整性的基础
5. 雪崩效应(Avalanche Effect)
定义:输入的极小改变会导致输出的巨大改变。
示例:
H("Bitcoin") = a1b2c3d4e5f6...(256位的十六进制数)
H("bitcoin") = 9z8x7w6v5u4t...(完全不同!)
改变一个字符 B→b,哈希值中大约一半的位被改变为什么重要:
- 无法通过部分数据修改来生成新的有效哈希值
- 防止了对交易或区块的微小篡改
- 使得任何欺骗企图都会被立即发现
常见的哈希函数
MD5(已废弃)
| 特性 | 说明 |
|---|---|
| 输出长度 | 128 位(16 字节) |
| 发布年份 | 1992 年 |
| 状态 | ⚠️ 已废弃 |
| 已知问题 | 已被找到碰撞,不再安全 |
为什么废弃:
- 在 2004 年,研究人员找到了 MD5 碰撞
- 在 2008 年,利用伪造的 SSL 证书证实了 MD5 的弱点
SHA-1(弱化)
| 特性 | 说明 |
|---|---|
| 输出长度 | 160 位(20 字节) |
| 发布年份 | 1995 年 |
| 状态 | ⚠️ 不再推荐 |
| 已知问题 | 已被找到碰撞,仍可用但不安全 |
为什么弱化:
- 2017 年首次公开演示 SHA-1 碰撞(Google 项目)
- 浏览器逐步放弃对 SHA-1 证书的支持
SHA-256(比特币使用)
| 特性 | 说明 |
|---|---|
| 输出长度 | 256 位(32 字节) |
| 发布年份 | 2001 年(SHA-2 家族) |
| 状态 | ✅ 推荐使用 |
| 应用领域 | 比特币、以太坊、TLS 等 |
| 安全性 | 目前认为是安全的 |
特点:
- 产生一个 256 比特的哈希值
- 计算相对快速
- 业界标准,经过数十年验证
SHA-512
| 特性 | 说明 |
|---|---|
| 输出长度 | 512 位(64 字节) |
| 发布年份 | 2001 年(SHA-2 家族) |
| 状态 | ✅ 推荐使用 |
| 应用领域 | 需要更高安全性的应用 |
特点:
- 输出长度是 SHA-256 的两倍
- 提供更高的安全裕度
- 计算速度略低于 SHA-256
RIPEMD-160(比特币使用)
| 特性 | 说明 |
|---|---|
| 输出长度 | 160 位(20 字节) |
| 发布年份 | 1996 年 |
| 应用领域 | 比特币地址生成 |
| 特点 | 比特币特有的选择 |
在比特币中的角色:
- 用于从公钥生成比特币地址
- 生成的地址更短(20 字节而不是 32 字节)
- 结合 SHA-256 使用:
RIPEMD160(SHA256(pubkey))
比特币中的哈希函数
比特币使用的两个主要哈希函数
1. SHA-256 的双重应用
在比特币中,SHA-256 通常被应用两次:
Double SHA-256:
result = SHA256(SHA256(data))
为什么双重应用?
- 增加安全性
- 防止 SHA-256 的某些已知弱点(如长度扩展攻击)
- 形成比特币的标准实践应用场景:
- 计算交易 ID(Transaction ID, TXID)
- 计算区块哈希
- 验证工作量证明
- 创建 Merkle 树
2. SHA-256 + RIPEMD-160 组合
比特币地址生成流程:
私钥 → 公钥 → SHA256(公钥) → RIPEMD160(结果) → 比特币地址
例如:
1. 公钥:0x0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798
2. SHA256 结果:0x62E907B15CBF27D5425399FBEB6D815C69A4991968B79A88C39A7D4F44FC0F9E
3. RIPEMD160 结果:0x62E907B15CBF27D5425399FBEB6D815C69A4991968B79A88C39A7D4F44FC0F9E(20字节)
4. 最终地址:1A1z7agoat4eiX8nSBLw6KvLncesTiGQwP哈希函数的应用
1. 交易完整性验证
场景:验证一笔交易是否被篡改
过程:
1. 接收方收到交易数据:
{
"input": "1A1z...",
"output": "1B2y...",
"amount": 1.5,
"hash": "abc123def456..."
}
2. 重新计算交易哈希:
calculated_hash = SHA256(SHA256(transaction_data))
3. 对比哈希值:
if calculated_hash == received_hash:
✅ 交易未被篡改
else:
❌ 交易已被篡改,拒绝2. 区块链结构维护
区块链结构:
区块 #100000
├── 区块头
│ ├── 版本号
│ ├── 前一区块哈希:abc...(指向区块 #99999)
│ ├── Merkle 根哈希:def...(所有交易的汇总)
│ ├── 时间戳
│ └── 难度目标
├── 交易数据
└── 区块哈希:xyz...(通过哈希区块头生成)
↓
区块 #100001
├── 区块头
│ ├── 版本号
│ ├── 前一区块哈希:xyz...(指向区块 #100000) ← 这形成了"链"
│ ├── Merkle 根哈希:ghi...
│ ├── 时间戳
│ └── 难度目标
├── 交易数据
└── 区块哈希:uvw...
链式结构的意义:
- 改变旧区块会改变其哈希值
- 这会使之后所有区块的"前一区块哈希"不匹配
- 整条链都会失效,容易被检测到3. 挖矿工作量证明
挖矿的本质:找到一个符合条件的哈希值
步骤:
1. 矿工选择一些待打包的交易
2. 构造区块模板:
{
"previous_block_hash": "abc123...",
"merkle_root": "def456...",
"timestamp": 1234567890,
"difficulty_target": 0x00000000ffff0000000000000000000000000000000000000000000000000000,
"nonce": 0 ← 这个值会不断改变
}
3. 不断改变 nonce(随机数),计算:
block_hash = SHA256(SHA256(block_header))
4. 检查条件:
if block_hash < difficulty_target:
✅ 找到有效区块!
else:
✅ nonce += 1,继续尝试
示例:
- nonce = 0: 计算结果 = 0x9abc... (太大,不符合)
- nonce = 1: 计算结果 = 0x8def... (太大,不符合)
- nonce = 2: 计算结果 = 0x00000000abcd... (✅ 符合条件!)4. Merkle 树构建
多笔交易的汇总过程:
交易列表:TX1, TX2, TX3, TX4
第一层(交易哈希):
H1 = SHA256(SHA256(TX1))
H2 = SHA256(SHA256(TX2))
H3 = SHA256(SHA256(TX3))
H4 = SHA256(SHA256(TX4))
第二层(配对哈希):
H12 = SHA256(SHA256(H1 + H2))
H34 = SHA256(SHA256(H3 + H4))
第三层(Merkle 根):
Merkle_Root = SHA256(SHA256(H12 + H34))
用途:
- 一个 32 字节的值(Merkle 根)代表了所有交易
- 任何交易的改变都会改变 Merkle 根
- 轻客户端(SPV)可以通过验证 Merkle 根来验证交易5. 地址生成
从私钥生成比特币地址的完整过程:
1. 私钥
priv_key = 0xe9873d79c6d87dc0fb6a5778633389f4453213303da61f20bd67fc233aa33262
2. 生成公钥(使用 ECDSA)
pub_key = ECDSA_Generate(priv_key)
= 0x0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798
3. SHA-256 哈希
hash1 = SHA256(pub_key)
= 0x62E907B15CBF27D5425399FBEB6D815C69A4991968B79A88...
4. RIPEMD-160 哈希
hash2 = RIPEMD160(hash1)
= 0x62E907B15CBF27D5425399FBEB6D815C69A4991968B79A88
5. Base58Check 编码
address = Base58Check_Encode(0x00 + hash2)
= 1A1z7agoat4eiX8nSBLw6KvLncesTiGQwP
最终结果:1A1z7agoat4eiX8nSBLw6KvLncesTiGQwP安全性考量
哈希函数的安全隐患
1. 碰撞攻击(Collision Attack)
定义:找到两个不同的输入产生相同的输出
比如:
H(A) = H(B),其中 A ≠ B
对比特币的威胁:
- 如果两个不同的交易产生相同的哈希值,无法区分
- 攻击者可能伪造交易
- 影响:极高
防御:
- 选择抗碰撞性强的哈希函数(如 SHA-256)
- 及时更新到更强的算法(如 SHA-3)2. 前向碰撞(Pre-image Attack)
定义:给定哈希值,找到产生该哈希值的输入
比如:
已知:hash_value = 0xabcd1234...
求:找到 x 使得 H(x) = hash_value
对比特币的威胁:
- 如果可以反推,就能从地址推出私钥
- 影响:极高
防御:
- 使用单向哈希函数
- SHA-256 目前被认为是抗前向碰撞的3. 长度扩展攻击(Length Extension Attack)
定义:在已知 H(message) 的情况下,不知道 message,
但可以计算 H(message || additional_data) 而无需知道 message
对比特币的威胁:
- 直接威胁不大,因为比特币使用双重 SHA-256
- SHA256(SHA256(data)) 对长度扩展有天然的防护
防御:
- 使用双重哈希(比特币的做法)
- 使用 HMAC 等带密钥的哈希构造哈希函数的选择标准
比特币选择 SHA-256 和 RIPEMD-160 的理由:
| 标准 | SHA-256 | RIPEMD-160 |
|---|---|---|
| 安全性 | ✅ 经过充分验证 | ✅ 经过充分验证 |
| 计算速度 | ✅ 快速 | ✅ 快速 |
| 输出大小 | 256 比特 | 160 比特 |
| 应用广泛度 | ✅ 广泛(TLS、HTTPS等) | ⚠️ 较少 |
| 历史悠久度 | ✅ 数十年验证 | ✅ 数十年验证 |
常见问题
Q1: 为什么比特币使用双重 SHA-256?
A:
- 安全性增强:两次哈希比一次更难破解
- 防止长度扩展攻击:SHA-256 存在已知的长度扩展弱点,双重应用可以防御
- 历史传统:中本聪的设计选择,经过验证
- 兼容性:改变会导致所有现有地址和交易失效
Q2: 哈希碰撞是否会导致比特币失败?
A:
- 短期:SHA-256 的碰撞在计算上目前不可行
- 长期风险:如果 SHA-256 被破解,比特币可以升级到 SHA-3
- 不是致命的:比特币社区已经为此做了准备,可以通过软分叉升级
Q3: 为什么比特币地址的长度不是 32 字节?
A:
- SHA-256 输出 32 字节(256 位)
- RIPEMD-160 输出 20 字节(160 位)
- 原因:
- 减少地址长度,便于使用
- 提高隐私性(更难追踪密钥)
- 平衡安全性和实用性
Q4: 两个不同的输入会不会碰撞?
A:
- 理论可能性:存在,但概率极低
- 数值示例:
- SHA-256 可能的输出数:2^256(约 1.16 × 10^77)
- 宇宙中的原子数:约 10^80
- 概率:极其渺茫
- 实际中:视为不可能
Q5: 量子计算会威胁 SHA-256 吗?
A:
- Grover 算法威胁:理论上可以加速碰撞查询
- 影响程度:减半输出大小的安全性(256 比特 → 128 比特安全性)
- 仍然安全:128 比特的安全性仍然足够强大
- 长期应对:比特币社区已在研究量子抗性算法
