5.1 散列函数的原理与三大安全性质


5.1 散列函数的原理与三大安全性质

本节摘要:密码学散列函数把任意长度的输入压缩成固定长度的摘要——SHA-256 恒为 256 位——并要求三条安全性质:原像不可逆、第二原像不可行、抗碰撞。本节厘清它与加密的本质区别,用雪崩效应演示统计指纹,用生日攻击解释"抗碰撞成本为何只有摘要长度的一半",为后面两章的选型与事故复盘打地基。

从校验和到密码学指纹

把长文件压成一段短摘要的想法早于现代密码学:早期软件分发页上的 CRC 校验值就是为了让下载者核对文件是否损坏。但 CRC 与密码学哈希之间隔着一道鸿沟——CRC 防意外,不防人。任何人改动文件后都能重新算出一个配套的 CRC;而密码学哈希要求:改动一个比特,摘要就面目全非,且没有任何人——包括改动者——能为伪造的内容配出指定摘要。

工程定义很朴素:散列函数 H 把任意长度的输入映射为固定长度的输出,SHA-256 的输出恒为 256 位,SHA-512 恒为 512 位。它不是加密:没有密钥、不可逆、不是"解密回去"的关系——散列是压缩,信息在压缩中真实丢失(无穷多种输入对应同一个 256 位摘要),所谓"反推"从来不是算术意义上的还原,而是在海量候选中找到某一个能对上指纹的输入。

三条安全性质正是对这个"找"的过程的约束:

  • 原像抵抗:给定摘要 h,找不到 m 使 H(m) = h。攻击成本约 2²⁵⁶(对 SHA-256)——试遍整个摘要空间;
  • 第二原像抵抗:给定 m₁,找不到不同的 m₂ 使两者摘要相同。成本同样约 2²⁵⁶——这一条是"哈希再签名"(4.5 节)的安全前提:合同不会被偷换;
  • 碰撞抵抗:找到任意一对 m₁ ≠ m₂ 同摘要。成本只有约 2¹²⁸——生日攻击把穷举打了对折,这个平方根折扣是理解一切哈希事故的钥匙。

图:单向压缩与雪崩效应

图:单向压缩与雪崩效应

二、雪崩效应:指纹的统计底色

好的散列函数有一条可实测的性质——雪崩效应:输入翻转一个比特,输出的每个比特都以约一半的概率翻转,整个摘要看起来与原摘要毫无关联。这保证了密文的"指纹"不会泄露明文的任何局部结构——1.6 节频率分析的教训在这里以另一种形式生效:统计可测性必须是零。

用标准库实测一遍三种经典算法与雪崩:

import hashlib def bits_diff(a: bytes, b: bytes) -> int: """两个摘要的翻转比特数""" return sum(bin(x ^ y).count("1") for x, y in zip(a, b)) m1 = b"attack at dawn 2024" m2 = b"attack at dawn 2025" # 只改一个字符 for name in ("md5", "sha1", "sha256"): h1 = hashlib.new(name, m1).hexdigest() h2 = hashlib.new(name, m2).hexdigest() d1 = hashlib.new(name, m1).digest() d2 = hashlib.new(name, m2).digest() print(name, "摘要长度(位):", len(d1) * 8, "雪崩翻转位:", bits_diff(d1, d2)) # sha256 输出恒为 256 位;翻转位稳定在 128 附近——一半左右

输出可见:MD5 恒 128 位、SHA-1 恒 160 位、SHA-256 恒 256 位;两个只差一个字符的输入,SHA-256 摘要平均翻转约 128 位。摘要的"不可预测性"不是玄学,是可以每跑一次都复核的统计事实。

💡 关键直觉:散列函数是密码学里的"公证处"——它不保密任何东西,却让"内容是否原样"从一句空话变成一次比特比较。加密系统的完整性支点几乎全部落在这 256 位上。

常见问题与排错

问题一:摘要既然不可逆,数据库里的口令哈希为什么还是会被破解?因为"不可逆"说的是无法还原原文,而攻击者根本不需要还原——他只需枚举候选口令、逐个哈希比对。原像抵抗挡住的是从摘要反解,挡不住从候选正向试探。这正是 5.3 节慢哈希存在的理由:把"逐个试"的成本放大到不可行。

问题二:既然有加密,为什么还要哈希?加密保护的是"读不到",哈希证明的是"没改过",两者不互相替代。更重要的是,哈希无密钥、无状态,验证方不需要持有任何秘密即可复核——完整性校验恰恰需要这种"人人可验"的性质。

问题三:下载页给了 MD5 校验值,还能信吗?看威胁模型:防传输损坏够用;防蓄意篡改不够——攻击者若能替换文件,同样能替换旁边的校验值。正经的分发渠道会用签名机制把校验值本身也保护起来。

排错提示:同一文件在不同机器上算出的摘要不一致,九成是文本换行符差异或编码转换所致,而非算法出错;比对二进制文件,或先统一文本规范化,再谈摘要。

三性质对照与内部结构一瞥

性质 攻击形式 SHA-256 的攻击成本 服务场景
原像抵抗 给定摘要找原文 约 2 的 256 次方 口令存储、承诺
第二原像抵抗 给定原文找替身 约 2 的 256 次方 哈希再签名
碰撞抵抗 找任意一对同摘要 约 2 的 128 次方 完整性校验

内部结构也值得一眼:SHA-256 属于分组迭代式构造,把输入切成 512 位一块,用一个压缩函数把上一块的状态与下一块搅在一起,最后一块的内部状态直出为摘要。这个结构简单、高效,也留下了 5.2 节将要讨论的长度扩展税;理解它,后面两节的兴衰故事就都有了解剖学基础。

一个动手小验证

把本节代码里的明文换成同一个文件的两种版本(例如改一个字节),再各自算摘要对比:你会发现无论改动多小,两条摘要都面目全非,且两次运行之间摘要不会漂移——确定性加上雪崩,正是"指纹"两个字在密码学里的全部含义。顺手再验证一次映射方向:把任意一条摘要拿去当输入再哈希,得到的是另一个完全不同的指纹,而不是"上一层的原文"——单向性的体感,胜过十遍定义。

本节要点回顾

  • 散列不是加密:无密钥、单向、信息真实丢失,"反推"指找到匹配输入而非还原原文;
  • 三大性质:原像与第二原像约 2²⁵⁶,碰撞受生日攻击折扣仅约 2¹²⁸,安全分析永远看最小的那一项;
  • 雪崩效应:单比特翻转引发约半数输出位翻转,SHA-256 输出恒 256 位,均可实测验证;
  • 角色预告:抗碰撞支撑完整性校验,第二原像支撑哈希再签名,原像抵抗支撑口令存储。

性质立好了,算法的生死成败就有了统一的度量衡。下一节走进 MD5、SHA-1、SHA-2、SHA-3 四代更替的完整时间线,看每一次"退役"如何被公开实验钉死。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U