密码与加密基础篇(4):bcrypt / Argon2id 为什么比 MD5 更适合存密码?

发布时间:2026/7/13 16:16:17

密码与加密基础篇(4):bcrypt / Argon2id 为什么比 MD5 更适合存密码?
前面几篇我们已经把几个基础问题讲清楚了密码与加密基础篇1别再说 MD5 加密了编码、摘要、加密到底有什么区别-CSDN博客密码与加密基础篇2密码到底怎么存为什么 MD5 已经过时-CSDN博客密码与加密基础篇3salt 和 pepper 到底是什么为什么 salt 可以放数据库-CSDN博客第1篇MD5 不是加密而是摘要 / 哈希 第2篇密码不能明文存也不应该简单 MD5 存 第3篇salt 是公开随机扰动pepper 是服务端私有秘密这一篇继续往下讲一个更核心的问题为什么 bcrypt / Argon2id 比 MD5 更适合存密码很多老项目里密码存储可能还是这样String passwordHash md5(rawPassword);或者稍微增强一点String passwordHash md5(rawPassword salt);这套方案能跑也确实比明文存密码好。但从现代密码安全角度看它已经不够了。不是因为 MD5 不能生成 hash而是因为MD5 太快了而密码哈希恰恰不能追求快。这句话是理解 bcrypt / Argon2id 的关键。一、先说结论密码哈希不是越快越好我们平时做程序经常追求快接口要快 查询要快 缓存要快 算法要快 启动要快但是密码存储这个场景很特殊。密码哈希不能一味追求快。因为密码哈希面对的不是普通业务计算而是攻击者的离线破解。如果数据库泄漏攻击者拿到username salt password_hash他就可以在自己的机器上疯狂猜密码hash(123456 salt) hash(111111 salt) hash(password salt) hash(qwerty salt)然后和数据库里的password_hash比较。这个过程不需要再请求你的服务器。所以服务端的登录限流、验证码、风控对这种离线破解帮助有限。这时真正影响安全性的是攻击者每猜一次密码的成本。MD5 的问题就在这里它太快了。而 bcrypt / Argon2id 的设计目标就是让每次猜测都更贵。二、MD5 的问题不是“不能 hash”而是“太适合被暴力猜”MD5 当然可以把密码变成一个摘要值。比如123456 ↓ MD5 e10adc3949ba59abbe56e057f20f883e它也不可逆。也就是说不能直接从e10adc3949ba59abbe56e057f20f883e解密回123456但是攻击者不需要解密。攻击者只需要猜。比如他提前准备常见密码表123456 111111 12345678 password qwerty admin123然后逐个计算 MD5。如果算出来的结果和数据库里一样就说明猜中了。所以很多人说“MD5 被破解了”严格来说不一定是被解密而是被猜中了。密码越弱越容易被猜中。MD5 越快攻击者猜起来越便宜。这才是核心问题。三、加 salt 以后MD5 还不够吗加 salt 比不加 salt 好。比如不用 salt用户AMD5(123456) xxx 用户BMD5(123456) xxx两个用户密码一样hash 也一样。攻击者还能用通用彩虹表快速匹配。加了 salt 后用户AMD5(123456 saltA) hashA 用户BMD5(123456 saltB) hashB即使两个人密码一样最终 hash 也不同。这很好。但是还不够。因为数据库泄漏时salt 通常也在数据库里。攻击者拿到salt abc001 password_hash xxxxxx他仍然可以针对这个 salt 猜MD5(123456 abc001) MD5(111111 abc001) MD5(password abc001)salt 的作用是让攻击者不能用一张通用表横扫所有用户。但 salt 不能解决 MD5 太快的问题。所以MD5 salt 比 MD5 好但仍然不是现代密码存储的推荐方案。四、密码哈希到底需要什么能力密码哈希和普通文件摘要不一样。普通文件摘要追求的是计算快 结果稳定 方便校验比如MD5(file) SHA-256(file)用来判断文件有没有损坏、有没有被修改。但密码哈希追求的是不可逆 每个用户独立 salt 计算成本可调 抗暴力猜测 抗批量破解所以密码哈希需要“慢”。准确说不是无脑慢而是对正常用户来说可以接受。 对攻击者批量猜测来说成本很高。正常用户登录一次密码校验多花几十毫秒、几百毫秒通常可以接受。但攻击者如果要猜几千万、几亿次这个成本就会被无限放大。这就是 bcrypt / Argon2id 的价值。五、什么是慢哈希慢哈希就是专门为密码存储设计的哈希方案。它和 MD5 / SHA-256 这类快速哈希的区别是MD5 / SHA 适合快速摘要、文件校验、完整性校验。 bcrypt / Argon2id / PBKDF2 适合密码存储故意提高计算成本。也就是说慢哈希不是算法写得差而是它故意让计算变贵。它的目标不是服务普通摘要场景而是对抗密码破解场景。一句话密码哈希慢不是缺点而是安全特性。六、bcrypt 是什么bcrypt 是一种成熟的密码哈希算法。它不是加密不能解密。它适合存密码因为它有几个关键特点1. 不可逆 2. 自带 salt 3. cost 成本可调 4. 计算速度故意变慢 5. 生态成熟工程落地简单bcrypt 生成的结果一般长这样$2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy这串内容不是单纯的 hash。它里面通常包含算法版本 cost 参数 salt 最终 hash 结果所以使用 bcrypt 时一般不需要自己额外保存 salt 字段。框架会自动处理。七、bcrypt 的 cost 是什么bcrypt 里有一个很重要的参数cost可以理解为计算成本。cost 越高计算越慢。比如cost 10 cost 12 cost 14数值越高密码哈希和验证所需时间越长。这对正常用户来说影响的是一次登录校验。但对攻击者来说影响的是每一次猜测。如果攻击者要猜一千万次那么每次成本增加一点总成本就会非常夸张。这就是 cost 的意义让系统可以随着硬件性能提升逐步提高密码破解成本。八、bcrypt 在 Spring Security 里怎么用Spring Security 里常见写法是Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); }注册时public void register(RegisterRequest request) { String rawPassword request.getPassword(); String encodedPassword passwordEncoder.encode(rawPassword); User user new User(); user.setUsername(request.getUsername()); user.setPassword(encodedPassword); userMapper.insert(user); }登录时public boolean login(LoginRequest request) { User user userMapper.findByUsername(request.getUsername()); if (user null) { return false; } return passwordEncoder.matches( request.getPassword(), user.getPassword() ); }重点是passwordEncoder.matches(rawPassword, encodedPassword)这里不是解密。bcrypt 不能解密。matches()的本质是从 encodedPassword 里解析出算法信息、cost、salt ↓ 用用户输入的 rawPassword 重新计算 ↓ 比较结果是否一致所以密码验证不需要还原明文。九、Argon2id 是什么Argon2 是新一代密码哈希算法家族。其中 Argon2id 是更推荐用于密码存储的变体之一。你可以先这样理解bcrypt 成熟、稳定、工程生态好。 Argon2id 更新、更强除了 CPU 成本还强调内存成本。MD5 快主要问题是攻击者可以用 GPU、专用硬件进行大规模并行计算。bcrypt 通过 cost 增加计算成本。Argon2id 更进一步它不仅关注计算时间还关注内存消耗。也就是说攻击者不是只要拼算力还要拼内存。这会让大规模并行破解变得更贵。十、Argon2id 为什么强调内存成本攻击者破解密码时常见思路是批量并行。比如同时猜很多密码。如果一个算法只消耗 CPU而且非常快那么攻击者可以通过大量硬件并行计算。Argon2id 引入内存成本后每次计算都需要占用一定内存。这样攻击者想大规模并行就不只是 CPU 问题还会遇到内存成本问题。所以 Argon2id 的目标是提高时间成本 提高内存成本 提高并行破解成本这就是它比传统快速哈希更适合密码存储的原因。十一、bcrypt 和 Argon2id 怎么选工程里不要陷入绝对化。可以这样看1. 普通 Spring Boot / Spring Security 项目优先用 bcrypt。原因很简单生态成熟 团队容易理解 Spring Security 支持好 落地成本低 线上经验多对大多数普通业务系统来说bcrypt 已经比 MD5 好很多。2. 新系统、安全要求更高可以考虑 Argon2id。比如金融 医疗 政企 高价值账户体系 安全要求较高的新系统Argon2id 的安全设计更新也更强调抗硬件并行破解。3. 兼容性、合规、老系统场景PBKDF2 也可以考虑。PBKDF2 的优势是标准化时间久 兼容性强 一些平台和合规场景支持好所以不是只有一个正确答案。更重要的是不要再用 MD5 当密码存储方案。十二、bcrypt / Argon2id / PBKDF2 对比可以用这张表理解算法是否适合密码存储主要特点工程建议MD5不推荐太快容易被暴力猜测不要用于新系统密码存储SHA-256不推荐直接用也是快速哈希不要直接 hash 密码MD5 salt不推荐比裸 MD5 好但仍然太快老系统过渡方案PBKDF2可用多轮迭代兼容性好合规、兼容场景可选bcrypt推荐自带 saltcost 可调成熟普通项目优先选择Argon2id推荐时间成本 内存成本高安全新系统优先考虑记住MD5 的问题不是不能哈希而是太快bcrypt / Argon2id 的价值是让攻击者猜密码的成本变高。十三、密码哈希参数怎么定很多人会问bcrypt cost 设置多少合适Argon2id 内存参数设置多少合适这个没有一个脱离业务的固定答案。因为它和服务器性能、并发量、登录接口压力、安全等级都有关系。原则是在用户体验和服务器承载能力可接受的范围内让密码校验尽量贵。不要盲目设置过高。如果 cost 太高可能会导致登录接口变慢 服务器 CPU 压力变大 高并发登录时被打爆 攻击者没打进来自己先扛不住所以实际项目里应该本地压测 测试环境压测 结合登录 QPS 结合服务器资源 选择一个可接受的成本参数安全不是只看算法名也要看参数。同样是 bcryptcost 太低安全性不足。 cost 太高系统扛不住。需要平衡。十四、为什么不能用 AES 加密密码存数据库有些人会说那我不用 MD5我用 AES 把密码加密存数据库不行吗不推荐。因为 AES 是可逆加密。如果后端能解密出用户原始密码就说明系统存在一把可以还原所有密码的密钥。一旦这个密钥泄漏所有用户密码都可能被还原。而密码存储的原则是系统不应该有能力还原用户原始密码。所以密码应该用不可逆的密码哈希算法而不是可逆加密。正确方向是密码 bcrypt / Argon2id / PBKDF2 Token AES-GCM Android Keystore因为密码不需要还原。Token 后续还要拿出来请求接口所以 Token 需要可逆加密。这两个不要混。十五、客户端要不要 bcrypt 后再传给后端一般不需要。App 登录时通常是用户输入原始密码 ↓ HTTPS/TLS 加密传输 ↓ 后端收到原始密码 ↓ 后端使用 bcrypt / Argon2id 校验如果客户端先 bcrypt 再传后端又认可这个 bcrypt 值登录那么这个 bcrypt 值本身就会变成“等价密码”。攻击者拿到这个值仍然可能直接登录。所以客户端不应该把“先 hash 一下”当成传输安全方案。传输安全靠 HTTPS。密码存储安全靠后端 bcrypt / Argon2id。客户端应该做的是不保存密码 不打印密码 不把密码放 URL 不把密钥写死到 APK 通过 HTTPS 请求登录接口十六、老项目 MD5 怎么迁移到 bcrypt如果数据库里已经是MD5(password)或者MD5(password salt)不能直接把历史数据改成 bcrypt。因为你没有用户原始密码。正确做法是兼容旧算法 登录成功后升级流程用户登录 ↓ 判断数据库密码格式 ↓ 如果是旧 MD5就用旧逻辑校验 ↓ 校验成功后拿用户本次输入的原始密码 ↓ 重新生成 bcrypt ↓ 更新数据库这样用户无感知系统逐步升级。十七、建议给密码字段加算法标识为了支持迁移数据库里的密码值最好能看出算法。比如{md5}e10adc3949ba59abbe56e057f20f883e {bcrypt}$2a$10$xxxxxxxxxxxxxxxxxxxx登录时public boolean login(String username, String rawPassword) { User user userMapper.findByUsername(username); if (user null) { return false; } String storedPassword user.getPassword(); if (storedPassword.startsWith({md5})) { String oldHash storedPassword.replace({md5}, ); if (oldHash.equalsIgnoreCase(md5(rawPassword))) { String newHash {bcrypt} passwordEncoder.encode(rawPassword); userMapper.updatePassword(user.getId(), newHash); return true; } return false; } if (storedPassword.startsWith({bcrypt})) { String bcryptHash storedPassword.replace({bcrypt}, ); return passwordEncoder.matches(rawPassword, bcryptHash); } return false; }这个思路很重要不要指望一次性把所有历史密码升级掉而是让用户登录成功时顺手升级。如果安全风险比较高也可以要求用户重置密码。十八、Spring Security 的 DelegatingPasswordEncoder 思路Spring Security 里有一种很适合多算法兼容的设计DelegatingPasswordEncoder它的思想是通过前缀标识算法 根据算法选择对应 PasswordEncoder类似{bcrypt}$2a$10$xxxx {pbkdf2}xxxx {noop}xxxx这样系统就能支持多种历史密码格式。这对老系统迁移非常有用。核心思想可以借鉴到自己的认证系统里密码字段不要只存 hash。 最好能知道这个 hash 是用什么算法生成的。十九、bcrypt / Argon2id 不是万能的虽然 bcrypt / Argon2id 比 MD5 更适合存密码但它们不是万能药。它们主要解决的是数据库泄漏后攻击者离线破解密码的成本问题。它们不能直接解决用户密码太弱 登录接口被在线爆破 密码被日志打印 客户端把密码存本地 Token 泄漏 钓鱼网站骗密码 撞库攻击所以完整认证安全还需要HTTPS 密码不打日志 登录失败限流 验证码 MFA / 二次验证 弱密码限制 改密后 Token 失效 异常登录风控 Token 安全存储安全不是单靠一个算法解决的。二十、常见误区误区 1MD5 不可逆所以很安全不对。不可逆只是基本要求。MD5 太快容易被批量猜测。误区 2MD5 salt 就够了不够。salt 解决相同密码同 hash 和预计算表问题但 MD5 仍然太快。误区 3bcrypt 是加密算法不准确。bcrypt 是密码哈希算法不是加密算法不能解密。误区 4密码应该加密存登录时解密比较不推荐。密码不应该可逆存储。应该用不可逆密码哈希。误区 5客户端先 hash 一下就安全了不对。客户端 hash 值可能变成等价密码。传输安全应该靠 HTTPS。误区 6用了 bcrypt 就不需要其他安全措施不对。bcrypt 解决的是密码存储问题不解决所有认证安全问题。二十一、最终总结bcrypt / Argon2id 为什么比 MD5 更适合存密码因为密码存储的核心不是简单生成一个摘要而是提高攻击者猜密码的成本。MD5 的问题是太快 适合文件校验 不适合密码存储 即使加 salt仍然容易被离线暴力猜测bcrypt 的优势是自带 salt cost 可调 计算成本可控 工程成熟 Spring Security 落地简单Argon2id 的优势是更新一代密码哈希方案 同时强调时间成本和内存成本 更适合高安全新系统如果压缩成一句话MD5 适合做快速摘要bcrypt / Argon2id 适合做密码哈希密码哈希不是要快而是要让攻击者猜不起。再放到整个认证体系里登录传输靠 HTTPS。 密码存储靠 bcrypt / Argon2id / PBKDF2。 salt 让每个用户的 hash 独立。 pepper 作为服务端秘密增强保护。 Token 本地存储靠 AES-GCM Android Keystore。 Token 失效靠后端 Redis / jti / tokenVersion。这套分工清楚了密码安全和 Token 安全就不会再混在一起。

相关新闻

关联规则挖掘实战:从布尔数据到Apriori算法在线闯关

关联规则挖掘实战:从布尔数据到Apriori算法在线闯关

2026/7/13 16:16:17

1. 关联规则挖掘入门:从购物篮到布尔数据第一次听说关联规则挖掘时,我正盯着超市收银台旁的货架发呆。为什么啤酒和尿布总放在一起?后来才知道这是数据挖掘领域的经典案例——通过分析顾客购物篮中的商品组合,发现"买尿布的爸…

2025大模型技术演进与部署优化实践

2025大模型技术演进与部署优化实践

2026/7/13 16:16:17

1. 2025年大模型技术演进全景图2025年成为大模型发展的关键分水岭,六大里程碑式研究成果重新定义了技术边界。DeepSeek-R1首次实现32B参数下的蒸馏量化部署,Qwen3系列突破多模态理解瓶颈,Kimi K2在长上下文窗口优化上取得突破性进展。这些进展…

TVA与具身智能融合的内在必然性(15)

TVA与具身智能融合的内在必然性(15)

2026/7/13 16:06:17

前沿技术探索:AI智能体视觉(TVA,Transformer-based Vision Agent)是依托Transformer架构与“因式智能体”理论所构建的颠覆性工业视觉技术,是集深度强化学习(DRL)、卷积神经网络(CNN…

MAA明日方舟助手:免费高效的终极自动化解决方案

MAA明日方舟助手:免费高效的终极自动化解决方案

2026/7/13 18:16:22

MAA明日方舟助手:免费高效的终极自动化解决方案 【免费下载链接】MaaAssistantArknights 《明日方舟》小助手,全日常一键长草!| A one-click tool for the daily tasks of Arknights, supporting all clients. 项目地址: https://gitcode.c…

Xenia Canary深度解析:如何让Xbox 360经典游戏在现代PC上重获新生?

Xenia Canary深度解析:如何让Xbox 360经典游戏在现代PC上重获新生?

2026/7/13 18:16:22

Xenia Canary深度解析:如何让Xbox 360经典游戏在现代PC上重获新生? 【免费下载链接】xenia-canary Xbox 360 Emulator Research Project 项目地址: https://gitcode.com/gh_mirrors/xe/xenia-canary 你是否曾经想过,那些尘封已久的Xb…

如何快速上手GEMMA:免费高效的全基因组关联分析工具完整指南

如何快速上手GEMMA:免费高效的全基因组关联分析工具完整指南

2026/7/13 18:16:22

如何快速上手GEMMA:免费高效的全基因组关联分析工具完整指南 【免费下载链接】GEMMA Genome-wide Efficient Mixed Model Association 项目地址: https://gitcode.com/gh_mirrors/gem/GEMMA 如果你正在寻找一款强大、免费且高效的全基因组关联分析工具&#…

深度解析OpenRGB:跨平台统一RGB设备控制的技术架构与实现原理

深度解析OpenRGB:跨平台统一RGB设备控制的技术架构与实现原理

2026/7/13 18:16:22

深度解析OpenRGB:跨平台统一RGB设备控制的技术架构与实现原理 【免费下载链接】OpenRGB Open source RGB lighting control that doesnt depend on manufacturer software. Supports Windows, Linux, MacOS. Mirror of https://gitlab.com/CalcProgrammer1/OpenRGB.…

Unity 2D精灵图动画优化:五大常见错误与解决方案

Unity 2D精灵图动画优化:五大常见错误与解决方案

2026/7/13 18:16:22

1. 项目概述:精灵图动画的“坑”与“道”在Unity里做2D游戏,精灵图动画(Sprite Animation)几乎是绕不开的基础功。这东西看着简单——不就是把几张图片按顺序播放嘛。但真上手做起来,尤其是想做得流畅、高效、不出岔子…

如何用ChatGPT把ROI提升3.8倍?——2024最新电商运营SOP流程图、数据看板配置及效果归因模型

如何用ChatGPT把ROI提升3.8倍?——2024最新电商运营SOP流程图、数据看板配置及效果归因模型

2026/7/13 18:06:22

更多请点击: https://kaifayun.com 第一章:ChatGPT电商运营的核心价值与ROI跃迁逻辑 ChatGPT并非仅是对话工具,而是电商运营中可量化的智能中枢——它通过语义理解、上下文记忆与实时决策能力,将用户意图、商品知识与营销策略动态…

Unity游戏文本翻译架构深度解析:XUnity.AutoTranslator的技术实现与工程实践

Unity游戏文本翻译架构深度解析:XUnity.AutoTranslator的技术实现与工程实践

2026/7/13 7:41:16

Unity游戏文本翻译架构深度解析:XUnity.AutoTranslator的技术实现与工程实践 【免费下载链接】XUnity.AutoTranslator 项目地址: https://gitcode.com/gh_mirrors/xu/XUnity.AutoTranslator XUnity.AutoTranslator作为Unity游戏社区中最成熟的文本翻译解决方…

openEuler Raspberry Pi Kernel设备驱动开发指南:为树莓派硬件添加支持

openEuler Raspberry Pi Kernel设备驱动开发指南:为树莓派硬件添加支持

2026/7/12 0:03:42

openEuler Raspberry Pi Kernel设备驱动开发指南:为树莓派硬件添加支持 【免费下载链接】raspberrypi-kernel It provides openEuler kernel source for Raspberry Pi 项目地址: https://gitcode.com/openeuler/raspberrypi-kernel 前往项目官网免费下载&…

openEuler系统集成测试实战:基于smoke-test套件的环境验证技巧

openEuler系统集成测试实战:基于smoke-test套件的环境验证技巧

2026/7/12 0:03:42

openEuler系统集成测试实战:基于smoke-test套件的环境验证技巧 【免费下载链接】integration-test The repo contains test suits for system integration test 项目地址: https://gitcode.com/openeuler/integration-test 前往项目官网免费下载:…

卡梅德生物技术快报|纯化重组蛋白:变异链球菌 SepM 截短蛋白载体构建、诱导优化与纯化重组蛋白全套参数方案

卡梅德生物技术快报|纯化重组蛋白:变异链球菌 SepM 截短蛋白载体构建、诱导优化与纯化重组蛋白全套参数方案

2026/7/13 0:05:25

1 研究背景与现存技术痛点(提出问题)在口腔微生物分子机制研究中,SepM 蛋白酶是调控变异链球菌群体感应、致龋菌素合成的核心功能蛋白,体外功能验证、抗体开发均依赖高纯度可溶性 SepM 蛋白。当前原核表达体系针对 SepM 存在三大技…

卡梅德生物技术快报|重组蛋白的表达和纯化:IMAC 金属螯合色谱全流程工艺手册|基质 - 配基 - 金属离子匹配与蛋白质分离纯化参数优化

卡梅德生物技术快报|重组蛋白的表达和纯化:IMAC 金属螯合色谱全流程工艺手册|基质 - 配基 - 金属离子匹配与蛋白质分离纯化参数优化

2026/7/13 0:05:25

1 研究背景与现存技术痛点(提出问题)基因工程、蛋白质组学、生物制药研发流程中,蛋白质分离纯化是决定下游实验成败的关键环节。当前实验室常规蛋白质分离纯化工艺存在三类难以标准化的技术瓶颈:传统离子交换、分子筛层析无特异性…

卡梅德生物技术快报|蛋白质分离纯化:肠激酶可溶性原核表达 + 两步层析全参数|标准化蛋白质分离纯化 SOP

卡梅德生物技术快报|蛋白质分离纯化:肠激酶可溶性原核表达 + 两步层析全参数|标准化蛋白质分离纯化 SOP

2026/7/13 0:05:25

研究痛点提出(提出问题)重组肠激酶是融合标签切除核心工具酶,当前原核表达体系存在三大标准化难题,直接阻碍可复现的蛋白质分离纯化流程搭建:Trx、GST、单 SUMO 标签融合产物绝大多数为包涵体,沉淀占比超 9…