4. 密码学基础(三):哈希算法(MD5、SHA-1、SHA-256)的原理、特点与应用场景

哈希算法(Hash Algorithm)是密码学中一类重要的单向函数。它能够将任意长度的输入数据(消息)映射为固定长度的输出值(哈希值、摘要或指纹)。在 HTTPS 通信中,哈希算法主要用于完整性校验、数字签名以及证书指纹,确保数据在传输过程中未被篡改。

4.1 哈希算法的核心特性

一个安全的密码学哈希算法必须满足以下三个基本特性:

  • 抗原像性(Preimage Resistance):给定哈希值 \( h \),在计算上无法找到原始输入 \( m \) 使得 \( H(m) = h \)。
  • 抗第二原像性(Second Preimage Resistance):给定输入 \( m_1 \),在计算上无法找到另一个不同的输入 \( m_2 \) 使得 \( H(m_1) = H(m_2) \)。
  • 抗碰撞性(Collision Resistance):在计算上无法找到任意两个不同的输入 \( m_1 \) 和 \( m_2 \) 使得 \( H(m_1) = H(m_2) \)。
💡 关键概念: 抗碰撞性是哈希算法安全性的核心。一旦算法被证明存在可行的碰撞攻击,该算法即被视为不安全,应停止在安全敏感场景中使用。

4.2 常见哈希算法对比

下表对比了 MD5、SHA-1 和 SHA-256 三种经典哈希算法的核心参数与安全状态:

算法 输出长度(位) 输出长度(字节) 安全状态 主要应用场景(历史/当前)
MD5 128 16 不安全(已攻破) 文件校验(已淘汰)、旧系统兼容
SHA-1 160 20 不安全(已攻破) 数字签名(已淘汰)、Git 版本控制
SHA-256 256 32 安全(推荐使用) HTTPS 证书签名、TLS 1.2/1.3、区块链

4.3 算法原理与工作流程

4.3.1 MD5(Message Digest Algorithm 5)

MD5 由 Ronald Rivest 于 1991 年设计,输出 128 位摘要。其处理流程包括:填充(使消息长度对 512 取模余 448)、附加 64 位长度值、初始化 4 个 32 位寄存器、进行 64 轮压缩函数运算。2004 年,中国密码学家王小云团队提出了高效的 MD5 碰撞攻击方法,使其不再适用于安全场景。

4.3.2 SHA-1(Secure Hash Algorithm 1)

SHA-1 由美国国家标准与技术研究院(NIST)于 1995 年发布,输出 160 位摘要。其结构类似于 MD5,但增加了 5 个 32 位寄存器和 80 轮运算。2017 年,Google 与 CWI Amsterdam 合作展示了首个实用的 SHA-1 碰撞攻击(SHAttered 攻击),标志着 SHA-1 的正式退役。

4.3.3 SHA-256(Secure Hash Algorithm 256)

SHA-256 属于 SHA-2 家族,由 NIST 于 2001 年发布,输出 256 位摘要。它使用 8 个 32 位工作寄存器和 64 轮运算,具有更强的抗碰撞能力。目前是 HTTPS 证书签名和 TLS 协议中最广泛使用的哈希算法。

哈希算法通用工作流程 任意长度输入 填充 + 长度 (512位分组) 压缩函数 (多轮迭代) 固定长度摘要 无论输入是 1 字节还是 1GB,输出长度始终固定(如 SHA-256 为 32 字节)

4.4 应用场景详解

4.4.1 HTTPS 证书签名与完整性

在 HTTPS 中,CA 使用哈希算法(通常是 SHA-256)对服务器证书内容计算摘要,然后使用自己的私钥对该摘要进行加密,形成数字签名。浏览器验证签名时,会重新计算证书的 SHA-256 摘要,并与 CA 公钥解密后的摘要进行比对。如果一致,则证明证书未被篡改且由可信 CA 签发。

4.4.2 文件完整性校验

软件分发网站通常提供文件的 SHA-256 哈希值。用户下载文件后,在本地计算相同哈希值并与官方值比对,以确认文件在下载过程中未被损坏或植入恶意代码。

📝 示例: 使用 OpenSSL 计算文件的 SHA-256 哈希值
openssl dgst -sha256 example_file.zip
# 输出示例:SHA256(example_file.zip)= a1b2c3d4e5f6... (64位十六进制)

4.4.3 密码存储

现代系统不会直接存储用户密码明文,而是存储密码的哈希值(通常还会加盐)。当用户登录时,系统计算输入密码的哈希值并与存储值比对。由于哈希算法的单向性,即使数据库泄露,攻击者也无法直接还原原始密码。

⚠️ 安全警告: 直接使用 MD5 或 SHA-1 存储密码是极其危险的。应使用专门的密码哈希函数(如 bcrypt、scrypt、Argon2)或至少使用 SHA-256 配合随机盐值(Salt)进行多次迭代哈希。

4.5 哈希算法在 HTTPS 中的角色

在 TLS 握手过程中,哈希算法承担了多重关键角色:

  • 证书验证:验证服务器证书的数字签名完整性。
  • 消息认证码(HMAC):TLS 记录协议使用 HMAC(基于哈希算法)确保每个数据包的完整性和真实性。
  • 密钥派生:TLS 1.2 使用 PRF(伪随机函数,基于 HMAC-SHA256)从主密钥派生出会话密钥。
  • 证书透明度(CT):使用 Merkle 树(基于 SHA-256)记录所有已签发证书,防止 CA 签发恶意证书。
哈希算法在 HTTPS 中的关键应用位置 客户端(浏览器) 服务器 TLS 握手 证书验证 密钥派生 数据加密传输 使用 SHA-256 验证证书签名 HMAC-SHA256 保证记录完整性 PRF 基于 HMAC-SHA256 派生密钥 AEAD 加密(如 AES-GCM)内建完整性

4.6 安全建议与最佳实践

  1. 全面淘汰 MD5 和 SHA-1:在 HTTPS 配置、数字签名、代码签名等任何安全敏感场景中,禁止使用 MD5 和 SHA-1。
  2. 默认使用 SHA-256:对于 TLS 证书签名、文件完整性校验、消息认证码等场景,优先选择 SHA-256 或更高强度的 SHA-384/SHA-512。
  3. 关注 SHA-3 进展:虽然 SHA-256 目前安全,但应关注 NIST 标准化的 SHA-3 算法,为未来迁移做准备。
  4. 避免哈希算法单独使用:在密码存储等场景中,不要单独使用哈希算法,应结合盐值和慢速哈希函数。
🔐 配置检查: 在 Nginx 或 Apache 的 HTTPS 配置中,确保 ssl_ciphers 指令只包含支持 SHA-256 的密码套件,并排除任何使用 MD5 或 SHA-1 的套件。