密码学入门:对称加密与非对称加密、哈希函数、数字签名

说实话,很多做身份认证的人,最后栽跟头都栽在密码学基础上。不是因为他们不懂算法原理,而是不知道什么时候该用什么。我见过不少项目,用 AES 去加密密码,用 MD5 去做签名——嗯,这都是典型的“会用工具但用错了地方”。

这一章,咱们就把密码学的四个核心模块捋清楚。你不需要成为密码学家,但得知道它们各自管什么事、有什么坑。

对称加密:快,但密钥怎么给?

对称加密,说白了就是加密和解密用同一把钥匙。你拿钥匙锁门,别人拿同一把钥匙开门。

最常见的算法是 AES(Advanced Encryption Standard)。我个人习惯用 AES-256-GCM,因为它不光加密,还能校验数据有没有被篡改。

核心要点: 对称加密适合加密大量数据,因为速度快。但密钥分发是个大问题——你怎么安全地把钥匙交给对方?

我在项目中遇到过一件事:两个服务之间用 AES 加密通信,密钥写死在配置文件里。结果运维不小心把配置文件传到了公开的 Git 仓库……嗯,那天晚上我加班到凌晨三点。

AES 使用示例(伪代码)

// 加密
key = "这是一个32字节的密钥"
plaintext = "用户身份证号: 110101199001011234"
ciphertext = AES_256_GCM_Encrypt(plaintext, key)

// 解密
decrypted = AES_256_GCM_Decrypt(ciphertext, key)
// decrypted == "用户身份证号: 110101199001011234"
避坑: 千万不要用 ECB 模式!它会把相同明文加密成相同密文,攻击者一看就知道哪些数据是重复的。我曾经审计过一个老系统,ECB 模式加密的图片,轮廓都看得一清二楚。

非对称加密:慢,但解决了密钥分发

非对称加密有两把钥匙:公钥和私钥。公钥可以公开,私钥自己藏好。你用公钥加密,只有私钥能解开。

你想想看,这解决了什么问题?对,密钥分发问题。别人用你的公钥加密数据,只有你能解密。不需要偷偷摸摸传密钥了。

主流算法是 RSA 和 ECC(椭圆曲线)。我个人更倾向 ECC,同样的安全强度下,它的密钥更短、计算更快。比如 ECC-256 的安全性和 RSA-3072 差不多,但密钥长度只有 1/10。

特性 对称加密(AES) 非对称加密(RSA/ECC)
密钥数量 1 个 2 个(公钥 + 私钥)
速度 快(GB/s 级别) 慢(MB/s 级别)
密钥分发 困难 容易
典型用途 加密大量数据 加密小数据、数字签名、密钥交换
实战技巧: 实际系统中,我们通常混合使用:用非对称加密传输对称密钥,然后用对称密钥加密实际数据。这就是 HTTPS 的底层逻辑。

哈希函数:不可逆的“指纹”

哈希函数能把任意长度的数据,变成固定长度的“摘要”。而且它是单向的——从摘要推不回原文。你想想看,这像不像给人打指纹?指纹能识别身份,但你不能从指纹还原出整个人。

常见的哈希算法有 SHA-256、SHA-3。至于 MD5 和 SHA-1,我建议你直接忘掉它们——它们已经被攻破了,碰撞攻击成本极低。

哈希的三大用途:
  • 存储密码: 只存哈希值,不存明文。即使数据库泄露,攻击者也拿不到原始密码。
  • 数据完整性校验: 下载文件后算一下哈希,和官方对比,就知道文件有没有被篡改。
  • 数字签名的基础: 先对消息做哈希,再对哈希值签名,效率高得多。

我曾经帮一个客户做安全审计,发现他们用 SHA-1 做代码签名校验。我跟他们说:“SHA-1 已经不安全了,Google 在 2017 年就演示了碰撞攻击。” 他们不信,直到我现场演示了两份不同代码生成相同 SHA-1 哈希……

重要提醒: 存储密码时,不要只用哈希!一定要加盐(salt),而且要用慢哈希算法,比如 bcrypt、scrypt、Argon2。为什么?因为不加盐的话,攻击者可以用彩虹表一秒破解几亿个密码。

数字签名:证明“是你写的”

数字签名解决的是身份认证和不可否认性问题。你想想看,你怎么证明一份电子合同是你签的?怎么证明它没有被篡改过?

数字签名的流程是这样的:

  1. 发送方对消息做哈希,得到摘要。
  2. 发送方用自己的私钥加密摘要,生成签名。
  3. 接收方用发送方的公钥解密签名,得到摘要 A。
  4. 接收方自己对消息做哈希,得到摘要 B。
  5. 如果 A == B,说明消息确实是发送方签的,且没有被篡改。

常用的签名算法有 RSA-PSS、ECDSA、EdDSA(比如 Ed25519)。我个人习惯用 Ed25519,它比 ECDSA 更快、更安全,而且实现不容易出侧信道漏洞。

避坑指南: 我曾经见过一个项目,用 RSA 做签名时没有做填充(padding),直接对哈希值做裸加密。这会导致选择明文攻击。正确的做法是用 PSS 填充模式。

知识体系总览

下面这张图把四个核心模块的关系画清楚了。你可以看到,哈希函数是数字签名的基石,而非对称加密又为对称加密解决了密钥分发问题。

密码学四大核心模块 对称加密 非对称加密 哈希函数 数字签名 混合加密 私钥签名 / 公钥验签 先哈希,再签名 💡 实际系统中的组合方式: • HTTPS:非对称加密交换对称密钥 → 对称加密传输数据 • 数字证书:哈希函数生成摘要 → 非对称加密签名 → 验证身份 • JWT:哈希(HMAC)或非对称签名保证 Token 不被篡改

实战中的选择建议

说了这么多理论,最后给点实在的。如果你在做身份认证系统,我的建议是:

  • 存储密码: 用 Argon2id 或 bcrypt,别用 SHA-256 裸哈希。
  • 传输加密: 直接用 TLS 1.3,别自己实现加密协议。
  • 数字签名: 优先用 Ed25519,其次是 ECDSA P-256。
  • 数据完整性: 用 SHA-256 或 SHA-3,别碰 MD5 和 SHA-1。
  • 密钥管理: 用硬件安全模块(HSM)或密钥管理服务(KMS),别把密钥写代码里。
一句话总结: 对称加密管速度,非对称加密管分发,哈希函数管完整性,数字签名管身份。四者配合,才能构建安全的身份认证系统。