BCrypt vs MD5:加盐在登录流程和数据库泄露中的作用
背景:BCrypt和MD5的区别
BCrypt和MD5是两种常见的密码哈希算法,但设计目标不同:
- MD5:快速、无加盐,同一个密码总是生成相同哈希,易被彩虹表攻击。
- BCrypt:内置随机salt和工作因子,每次加密结果不同,且计算速度可控。
网上常说BCrypt能防彩虹表攻击,但我在登录流程中产生了一个疑问:如果前端传明文密码给后端,BCrypt的加盐真的有优势吗?下面我将逐步分析并解答。
彩虹表攻击与MD5的弱点
彩虹表攻击是这样工作的:
- 攻击者预先计算大量密码的MD5哈希,生成"密码-哈希"对照表。
- 如果数据库泄露,拿到哈希值(比如"e10adc..."),直接查表就能得到"123456"。
MD5没有加盐,同一个密码永远生成同一个哈希,这让彩虹表非常高效。
登录流程:BCrypt和MD5的实际操作
先看看典型的登录流程:
- 用户输入明文密码(比如"123456"),前端传给后端。
- 后端拿到明文密码,加密后与数据库中的哈希比对。
- 如果匹配,登录成功。
MD5的处理方式
- 数据库存的是纯哈希(比如"e10adc...")。
- 后端收到"123456",用MD5加密得到"e10adc...",与数据库比对。
BCrypt的处理方式
- 数据库存的不是单纯的哈希,而是一个组合字符串(比如
$2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy):$2a$10$:版本和工作因子。N9qo8uLO...:随机salt。- 后面部分:哈希值。
- 后端收到"123456"后:
- 从数据库中提取该用户的salt(比如
N9qo8uLO...)。 - 用这个salt和"123456"计算BCrypt哈希。
- 将计算结果与数据库中的哈希部分比对。
- 从数据库中提取该用户的salt(比如
关键点:BCrypt不是"直接比对前端传来的哈希",而是拿前端的明文密码,用数据库里已有的salt重新计算哈希,再进行比对。
困惑解答:为什么攻击者不能直接试?
我一开始疑惑:如果攻击者调用后端接口,拿密码库逐一尝试(比如传"123456"、"password"等),后端不还是会用数据库的salt加密,最终匹配上吗?BCrypt和MD5有啥区别?
澄清登录流程中的逻辑
- MD5:后端收到明文,直接生成哈希并比对。攻击者在线尝试时,MD5计算极快(每秒可试成千上万次),加上没有salt,数据库泄露后还能用彩虹表直接查。
- BCrypt :后端收到明文,用数据库中的salt计算哈希。攻击者可以尝试调用接口,但:
- 不知道salt:salt存在数据库里,攻击者无法提前预计算哈希,只能在线实时提交明文让后端算。
- 计算慢:BCrypt的工作因子让每次计算耗时(比如0.1秒),每秒最多试10次,而非MD5的成千上万次。
换句话说,攻击者就算能调用后端接口,也只能"猜明文",而不能直接提交哈希值跳过计算。因为后端只接受明文,用已有的salt重新算,这一步没法绕过。
在线攻击的对比
- MD5:在线暴力破解很快,数据库泄露后更惨(彩虹表秒破)。
- BCrypt:在线暴力破解受限于工作因子,速度极慢(比如10次/秒),而且salt让预计算无效。
所以在登录流程中,BCrypt确实比MD5有优势:它减缓了在线攻击的速度。
数据库泄露时的防护
BCrypt的加盐在数据库泄露时作用更明显:
- MD5:泄露后,彩虹表直接查出明文。
- BCrypt:泄露的是salt+哈希组合,salt随机且不同,攻击者无法用彩虹表,只能针对每个用户暴力破解,而工作因子又让破解成本飙升。
结论:BCrypt的双重优势
BCrypt不仅在数据库泄露时能防止彩虹表攻击,在登录流程中也有突出优势:
- 在线攻击:工作因子减慢计算速度,限制暴力破解效率。
- 离线攻击:加盐让彩虹表失效,数据库泄露后仍安全。
相比之下,MD5在两种场景下都脆弱:在线快、离线更快。所以,BCrypt的加盐和工作因子并不是"只防数据库泄露",而是在整个安全体系中都比MD5更强。疑问彻底解开了!