📘 概述
argon2 是一种现代、安全的密码哈希算法 ,用于安全存储用户密码或其他敏感认证信息。 它不是加密(encryption),而是单向哈希(hashing) ------ 无法解密。
Argon2 是 2015 年密码哈希竞赛(PHC)的获胜算法,目前公认为业界最安全、最先进的哈希方案之一。
🧠 核心思想
| 概念 | 说明 |
|---|---|
| 哈希(Hash) | 将明文密码转换为固定长度的随机字符串(不可逆) |
| 加盐(Salt) | 在哈希前加入随机数据,使每个结果唯一 |
| 验证(Verify) | 用输入密码重新计算哈希并比对是否一致 |
| 不可逆 | 无法"解密"得到原始密码 |
🧰 Node.js 示例
js
import argon2 from "argon2";
async function example() {
const password = "123456";
// 1️⃣ 生成哈希
const hash = await argon2.hash(password);
console.log("哈希结果:", hash);
// 示例输出: $argon2id$v=19$m=65536,t=3,p=4$YWFh...ZGRk
// 2️⃣ 验证密码
const isValid = await argon2.verify(hash, "123456");
console.log("验证结果:", isValid); // true
// 3️⃣ 错误示例
console.log(await argon2.verify(hash, "wrong")); // false
}
example();
🧩 Python 等价实现(argon2-cffi)
python
from argon2 import PasswordHasher
ph = PasswordHasher()
hash = ph.hash("123456")
print(hash)
# 验证密码
ph.verify(hash, "123456") # ✅ 正确
安装:
bash
pip install argon2-cffi
🧩 自动加盐机制(Salt)
Argon2 在生成哈希时会自动加入随机盐(salt) 。 每次调用 argon2.hash(),即使输入的密码相同,生成的哈希也不同。
例子:
js
const hash1 = await argon2.hash("123456");
const hash2 = await argon2.hash("123456");
console.log(hash1);
console.log(hash2);
输出(注意不同):
ini
$argon2id$v=19$m=65536,t=3,p=4$4tYpH...$1mSw...
$argon2id$v=19$m=65536,t=3,p=4$kqC6z...$TnsA...
✅ 原因:每次都会生成一个随机盐。 盐会自动包含在哈希字符串中,无需手动保存或管理。
验证时的工作原理
argon2.verify(stored_hash, input_password) 会自动:
- 从哈希字符串中解析盐和算法参数;
- 用输入密码和解析出的盐重新计算哈希;
- 比对结果是否一致。
👉 所以只要保存这一整串哈希字符串,就足够验证密码,无需额外存盐。
🔒 哈希结果结构解析
ruby
$argon2id$v=19$m=65536,t=3,p=4$<salt>$<hash>
| 字段 | 含义 |
|---|---|
| argon2id | 使用的 Argon2 类型(推荐) |
| v=19 | 算法版本 |
| m=65536 | 内存成本(越大越安全) |
| t=3 | 迭代次数 |
| p=4 | 并行度 |
| salt | 随机盐 |
| hash | 哈希结果 |
⚠️ 重要特性
| 特性 | 说明 |
|---|---|
| 自动加盐 | ✅ 内置随机盐,每次不同 |
| 不可逆 | ❌ 不能解密还原原文 |
| 可验证 | ✅ 可用 verify() 检查密码是否匹配 |
| 抗暴力破解 | ✅ 需要大量内存和 CPU 时间 |
| 可配置 | 可调整内存成本(m)、迭代次数(t)、并行度(p) |
📎 小结
| 操作 | 方法 |
|---|---|
| 生成哈希 | await argon2.hash(password) |
| 验证密码 | await argon2.verify(hash, inputPassword) |
| 是否自动加盐 | ✅ 是 |
| 盐需保存吗 | ❌ 不需要(哈希中已包含) |
| Python 实现 | argon2-cffi |
🗒️ 记住: Argon2 是密码哈希算法,不是加密算法。 它的目标是让密码无法被还原,但能被安全地验证。