Luke a Pro

Luke Sun

Developer & Marketer

🇺🇦
EN||

密码学在解决什么问题

| , 3 minutes reading.

1. 为什么要关心这个问题?

一个开发者用 AES 加密用户密码。另一个用 MD5 签名 API 请求。第三个用 RSA 加密几个 GB 的视频文件。

三个都是错的。

不是因为这些算法有问题,而是因为他们用错了工具。就像用锤子锯木头——锤子没问题,你只是用错了方式。

密码学不是一个单一的东西。它是一个工具箱,每个工具解决特定的问题。在需要哈希的地方用加密,或者在需要签名的地方用哈希,你的「安全」系统就变成了一个隐患。

2. 定义

密码学 是通过数学技术保护信息的科学。它为恰好四个基本安全问题提供解决方案:

  1. 机密性: 保守秘密
  2. 完整性: 检测未经授权的修改
  3. 认证: 验证身份
  4. 不可否认性: 防止否认行为

每个问题需要不同的工具。没有单一算法能解决全部四个问题。

3. 密码学安全的四大支柱

机密性:「只有预期的接收者能读取」

问题: 你想发送一条只有 Alice 能读取的消息,即使 Eve 截获了它。

解决方案: 加密

  • 对称加密(AES、ChaCha20)
  • 非对称加密(RSA、ECIES)

它不解决什么:

  • 消息是否被篡改
  • 发送者是否是他们声称的那个人
  • 发送者是否能否认发送过它
# 机密性:AES 加密
ciphertext = aes_encrypt(plaintext, key)
# Eve 截获了密文但无法读取
# 但是:Eve 可以在不被检测的情况下修改密文!

完整性:「这条消息没有被篡改」

问题: 你收到一条消息,需要验证它在传输过程中没有被修改。

解决方案: 哈希函数和 MAC

  • 哈希函数(SHA-256、SHA-3)
  • 消息认证码(HMAC)

它不解决什么:

  • 保持消息内容的机密性
  • 证明是谁发送的消息(对于没有密钥的哈希)
# 完整性:哈希验证
original_hash = sha256(message)
# 稍后...
if sha256(received_message) != original_hash:
    raise TamperedMessageError()
# 但是:任何人都可以计算哈希——这不能证明是谁发送的!

认证:「这条消息来自它声称的发送者」

问题: 你收到一条声称来自 Alice 的消息。你如何验证它真的来自她?

解决方案: 数字签名和 MAC

  • 数字签名(RSA-PSS、ECDSA、EdDSA)
  • HMAC(使用共享密钥)

区别:

  • HMAC: 双方共享一个密钥。你知道它来自知道密钥的人。
  • 数字签名: 只有私钥持有者能签名。你可以用公钥验证。
# 认证:数字签名
signature = sign(message, alice_private_key)
# 任何人都可以验证
is_authentic = verify(message, signature, alice_public_key)

不可否认性:「发送者不能否认发送过这个」

问题: Alice 发给你一份合同。后来,她声称她从未发送过。你如何证明她发送过?

解决方案: 数字签名(仅限非对称!)

为什么 HMAC 不行: 使用 HMAC 时,双方共享同一个密钥。如果 Alice 有密钥,你也有密钥——你们任何一方都可能创建了这条消息。Alice 可以声称是写的。

为什么数字签名可以: 只有 Alice 的私钥能创建有效的签名。如果签名用她的公钥验证通过,它一定来自她的私钥。她无法否认。

# 不可否认性:只有非对称签名提供这个
signature = sign(contract, alice_private_key)
# Alice 不能声称她没签——只有她的私钥能创建这个签名

4. 算法-问题矩阵

问题哈希HMAC对称加密非对称加密数字签名
机密性
完整性✅*
认证
不可否认性

*哈希仅在你有原始哈希的可信副本时提供完整性验证。

5. 误用导致的常见灾难

灾难 1:加密密码

# 错误:用加密存储密码
encrypted_password = aes_encrypt(password, key)
database.store(encrypted_password)

# 问题:如果密钥被盗,所有密码立即暴露
# 另外:你为什么需要解密密码?

正确做法: 用 bcrypt/argon2 哈希密码。你永远不需要恢复原始密码——你只需要验证。

灾难 2:用哈希实现机密性

# 错误:用哈希当"加密"
"secure_data" = sha256(sensitive_data)

# 问题:哈希是单向的,但是确定性的
# 相同输入 = 相同输出 = 可能进行模式分析
# 而且你永远无法恢复原始数据

正确做法: 如果需要恢复数据,使用真正的加密。

灾难 3:用 HMAC 实现不可否认性

# 错误:用 HMAC 签合同
mac = hmac(contract, shared_secret)

# 问题:双方都有密钥
# Alice:"我没签这个——Bob 也有同样的密钥,他可能写的"

正确做法: 对任何需要不可否认性的东西使用数字签名。

灾难 4:用 RSA 加密大数据

# 错误:用 RSA 加密大文件
encrypted_video = rsa_encrypt(video_file, public_key)  # 极其慢!

# 问题:RSA 比 AES 慢约 1000 倍
# 另外:RSA 有消息大小限制

正确做法: 使用混合加密——用 AES 加密数据,用 RSA 加密 AES 密钥。

6. 真实系统如何组合工具

现实世界的安全需要多个密码学原语协同工作。

HTTPS/TLS 握手

┌─────────────────────────────────────────────────────────┐
│ 1. 密钥交换(机密性 + 认证)                             │
│    - ECDHE 实现前向保密                                 │
│    - 服务器证书(RSA/ECDSA 签名)                        │
├─────────────────────────────────────────────────────────┤
│ 2. 数据传输(机密性 + 完整性)                           │
│    - AES-GCM 加密                                       │
│    - 内置认证标签(完整性)                              │
└─────────────────────────────────────────────────────────┘

JWT(JSON Web Token)

┌─────────────────────────────────────────────────────────┐
│ Header.Payload.Signature                               │
├─────────────────────────────────────────────────────────┤
│ 签名提供:                                              │
│ - 完整性:令牌不能被修改                                │
│ - 认证:服务器可以验证发行者                            │
├─────────────────────────────────────────────────────────┤
│ 签名不提供:                                            │
│ - 机密性:Payload 是 Base64,不是加密的!               │
└─────────────────────────────────────────────────────────┘

7. 决策框架

选择密码学工具时,问:

你需要恢复原始数据吗?
├─ 否 → 考虑哈希
│   └─ 是密码吗?→ 使用 bcrypt/argon2
│   └─ 是用于完整性验证?→ 使用 SHA-256/SHA-3

├─ 是 → 你需要加密
│   └─ 谁持有密钥?
│       ├─ 同一方加密/解密 → 对称(AES)
│       └─ 不同方 → 非对称或混合

你需要证明是谁发送的吗?
├─ 可以接受共享密钥?→ HMAC
└─ 需要不可否认性?→ 数字签名

8. 本章小结

三点要记住:

  1. 一个算法,一个问题。 加密提供机密性。哈希提供完整性。签名提供认证和不可否认性。不要混淆它们。

  2. 不可否认性需要非对称密码学。 如果双方共享密钥,都无法证明对方发送了消息。只有数字签名提供不可否认性。

  3. 真实系统组合多个原语。 HTTPS 同时使用密钥交换、加密和认证。理解哪个工具做什么,有助于你理解协议为什么这样设计。

9. 下一步

现在我们理解了密码学解决的四个问题。但我们多次提到「对称」和「非对称」加密却没有解释区别。

在下一篇文章中,我们将探讨:为什么我们需要两种完全不同类型的加密?它们的权衡是什么,真实系统如何组合使用它们?