Argon2在C++中需依赖第三方库(如libargon2),不可手写;必须正确设置t_cost≥3、m_cost≥65536、parallelism≤4、hash_length=32,使用Argon2id;盐值须密码学安全随机生成且唯一;验证须用argon2_verify防时序攻击。

Argon2 在 C++ 中不是标准库函数,得用第三方实现
标准 C++ 没有 argon2_hash 或任何密码哈希原生支持。你必须引入像 PHC 官方 C 实现 这类成熟库,再用 C++ 封装调用。别试图自己写 Argon2——算法参数敏感、内存访问模式严格,手写极易引入侧信道或逻辑错误。
常见错误是直接 include 头文件却没链接 libargon2,编译时爆 undefined reference to argon2_hash。确保构建时加 -largon2(Linux/macOS)或正确配置 Windows 的 .lib。
使用场景明确:只用于密码注册/重置时的一次性哈希,绝不用于加密、签名或密钥派生以外的用途。
调用 argon2_hash 必须设对这四个参数
Argon2 安全性高度依赖参数选择,错一个就可能退化成可暴力破解的状态。官方推荐用 Argon2id(兼顾抗 GPU 和抗侧信道),而非 Argon2d 或 Argon2i。
立即学习“C++免费学习笔记(深入)”;
-
t_cost:迭代次数,建议 ≥ 3(低于 1 不安全,高于 10 显著拖慢登录) -
m_cost:内存消耗(KB),建议 ≥ 65536(即 64MB),太小易被 ASIC 破解 -
parallelism:线程数,通常设为 CPU 逻辑核数,但线上服务建议 ≤ 4 避免争抢 -
hash_length:输出长度,固定用 32 字节(256 位),别截短或加长
示例调用关键片段:
uint8_t hash[32];
int result = argon2_hash(t_cost, m_cost, parallelism,
(char*)password.c_str(), password.size(),
(char*)salt.data(), salt.size(),
hash, sizeof(hash),
NULL, 0, Argon2id, VERSION_NUMBER);盐值(salt)不能复用、不能硬编码、不能从用户输入生成
盐值唯一作用是让相同密码产生不同哈希,防止彩虹表和批量破解。它必须:
- 每次注册都用密码学安全随机数生成,如
std::random_device+std::uniform_int_distribution,或getrandom()(Linux) - 长度至少 16 字节;
argon2要求最小 8 字节,但 16 更稳妥 - 明文存数据库,和哈希一起;别加密盐——那毫无意义
- 绝不能用用户名、邮箱、时间戳等可预测值当盐
容易踩的坑:std::rand() 生成的 salt 是可预测的;用 time(nullptr) 当 salt 会导致同一秒注册的所有用户共用 salt。
验证密码时必须用 argon2_verify,且防范时序攻击
别自己 strcmp 哈希结果。argon2_verify 内部做了恒定时间比较(constant-time memcmp),避免通过响应时间差异泄露哈希前缀。
典型错误写法:
// ❌ 危险!可能触发时序侧信道
if (stored_hash == computed_hash) { ... }正确做法:
int result = argon2_verify(stored_encoded_string, // "$argon2id$v=19$m=65536,t=3,p=4$..."
(char*)password.c_str(), password.size(),
Argon2id);
if (result == ARGON2_OK) { /* 验证通过 */ }
else if (result == ARGON2_INVALID_HASH) { /* 编码格式错 */ }
else { /* 密码错 */ }注意:argon2_verify 输入的是完整 encoded string(含参数、salt、hash),不是裸哈希字节。解析失败会返回 ARGON2_INVALID_HASH,不是直接崩溃。
复杂点在于:encoded string 格式必须严格匹配原始哈希输出,比如参数顺序、base64 编码方式(argon2 用的是自定义 base64,不是 RFC 4648)。少一个 $ 或错一位字符,argon2_verify 就静默失败。



















