密码学基础:编码、哈希、加密与数字签名

学习 JWT 和 Argon2 前,必须先区分编码、哈希、加密和数字签名。它们看起来都能把原始文本变成“不容易看懂的字符串”,但目的完全不同。

1. 明文与密文

加密的核心目标是保密性:没有正确密钥的人不应读懂数据。

2. 编码不是加密

编码是为了让数据适合传输或存储,任何知道规则的人都能还原。

例如 Base64:

hello -> aGVsbG8=

Base64URL 是适合 URL 和 HTTP 场景的 Base64 变体,通常会:

JWT 的 Header 和 Payload 使用 Base64URL 编码。因此拿到 JWT 的人通常都能读取它们,不能把密码、银行卡号或密钥放入 Payload。

3. 哈希

哈希函数把任意长度的数据映射为固定长度摘要:

原始数据 --哈希函数--> 摘要

密码学哈希通常追求:

常见通用哈希算法有 SHA-256。它适合文件完整性、随机 Token 摘要等场景,但它计算很快,所以不适合直接哈希人类密码。密码通常较短且可猜测,攻击者可以高速尝试大量候选值。

4. 密码哈希

Argon2 属于专门的密码哈希算法。它故意消耗时间和内存,从而提高批量猜密码的成本。

密码哈希通常会使用随机盐(Salt):

密码 + 随机盐 + 成本参数 -> 密码哈希

盐不是密码,不需要保密。它用于确保:

node-argon2 默认会生成安全随机盐,并把算法类型、版本、成本参数、盐和结果编码在 PHC 字符串中:

$argon2id$v=19$m=65536,t=3,p=4$...盐...$...哈希...

数据库保存这一整串即可,不需要另外增加 salt 字段。

5. 对称加密

对称加密使用同一把密钥进行加密和解密:

明文 + 密钥 -> 密文
密文 + 同一密钥 -> 明文

例如 AES-GCM。它适合需要在未来取回原文的数据,例如加密保存某些业务机密。

密码不需要被服务端还原,所以密码应哈希,而不是加密保存。

6. 非对称加密

非对称密码学使用一对相关密钥:

不同算法可以用于加密或签名。不能简单理解为“私钥加密、公钥解密”,数字签名和加密是不同的密码学操作。

7. 消息认证码与数字签名

签名类机制主要解决两个问题:

JWT 常见的 HS256 实际使用 HMAC:签发方和验证方共享同一个 Secret。

signature = HMAC-SHA256(header.payload, secret)

RS256 使用 RSA 私钥签名、公钥验证:

签发服务:私钥签名
验证服务:公钥验证

签名不会隐藏 header.payload,只用于检测篡改并确认签发者。

8. 四类技术对比

技术 是否可逆 是否需要密钥 主要目标 示例
编码 表示和传输数据 Base64URL
通用哈希 数据摘要、完整性 SHA-256
密码哈希 安全保存密码 Argon2id
加密 隐藏数据内容 AES-GCM
签名/MAC 不用于还原 来源认证、防篡改 RS256、HS256

9. 和本教程的关系

用户密码
  -> Argon2id 密码哈希
  -> 数据库不保存明文

JWT Header + Payload
  -> Base64URL 编码,可被读取
  -> 使用 Secret 或私钥生成 Signature
  -> verify 检查签名与声明

最重要的结论:

普通 JWT 通常是编码加签名,而不是加密;Argon2 是密码哈希,而不是加密。