一个抗脱库的密码哈希方法

2023-07-14 19:43:56 +08:00
 chenjia404

我之前做过一个方案: 哈希(用户名+密码+网站名)发送给服务器,服务器拿到提交的哈希和用户名,再哈希(用户名+密码+网站名+盐),把最后一步的哈希存在一张哈希表里面,下次用户登录的时候,只需要验证哈希表中是否有元素即可。 修改密码的时候修改用户的盐,写入新的哈希记录就行了,而且哈希表越来越大,每个网站的哈希表都不一样,泄露也没有办法跑彩虹表。 哈希函数只要是在 sha1 以上的,基本上冲突的可能性就很小。 这个方案也不需要提交明文密码到服务器,过安全测评也好过。

2432 次点击
所在节点    奇思妙想
31 条回复
Liyuu
2023-07-17 23:36:24 +08:00
也就是说'网站名'可以换成任意一个常量,相当于加了一个没有存在库里的盐,这样吗?
dallaslu
2023-07-18 14:20:19 +08:00
大概是这样吧?

* 客户端计算 hash(user+pass+site),得出 user_hash
* 注册时客户端将 user 和 user_hash 发送到服务器,服务器建立 user 并创建对应 salt ,计算 hash(user+user_hash+site+salt) 得出 auth_hash ,将其存入一个与 user 无关联的表中
* 登录时服务器根据 user 查询 salt ,并计算 auth_hash ,如其在表中存在,则验证通过
* 修改密码时,根据旧密码计算出旧的 auth_hash 并删除之,然后创建新 salt 并保存新 auth_hash

被拖库时,攻击者只能看到 user 和对应 salt ,以及一堆无任何标识的 auth_hash ,既不能查表,也不能破解。

上面各位提到网站名 site ,其实在做 auth_hash 时用 hash(user+user_hash+salt) 即可,site 在此没有必要。这个方案主要就两点,客户端不发真实密码、服务器不保存 auth_hash 与用户的关联。

客户端发 hash 不发密码的出发点是什么呢?是怕被中间人嗅探、服务器日志记录吧,尽管保护了真实密码,但 user_hash 每次使用时都是不变的,在此网站也等同于密码,只起到有限的保护作用。

服务器不存 auth_hash 与用户的关联,的确将拖库后的破解难度提升了用户数量的倍数,如果有十万用户,从 auth_hash 暴力破解指定用户的 pass ,最多需要计算 256^20*256^20*100000 次
chenjia404
2023-07-18 20:27:38 +08:00
@dallaslu #22 旧的 auth_hash 不删除,这个表数据越多越好
dallaslu
2023-07-19 10:44:24 +08:00
@chenjia404 即使这个策略奏效,也只是将 256^40 变成 256^43 ,「几乎不可能」乘以十万也是「几乎不可能」
chenjia404
2023-07-19 16:10:48 +08:00
@dallaslu 恩,不过确实无法反向破解明文密码了,auth_hash 表公布都没有影响。
stamhe
2023-09-09 10:12:26 +08:00
@dode 嗨,想了解一下,你这个是你们项目有在使用的东西么?
dode
2023-09-09 21:22:42 +08:00
@stamhe 我们不涉及这个,我看到谷歌在用了
stamhe
2023-09-10 16:45:21 +08:00
@dode google 和 apple 他们接入的是 fido alliance 的 passkey 方案,这个方案是个残疾。不能用于工业应用。
CLMan
58 天前
自从加盐哈希流行以后,安全界为啥还要建议使用 Bcrypt 、argon2 这些密码存储专用的哈希算法呢,无非是担心现有及以后的硬件暴力破解通用哈希算法太快。至于彩虹表,已经是上个过时版本了。

而你认为设计很好的点“ auth_hash 与 user 并非一一对应”,反而是最大的漏洞,因为它们其实是 N:1 的关系( N 指 auth_hash 表的大小),意味着暴力破解时,可以碰撞的哈希值有 N 个。“这个表数据越多越好”,意味着破解的难度越低。

很多人以为,密码存储哈希值是避免用户的明文密码泄露,其实不然,是避免应用的明文密码泄露。如果是前者,那客户端密码 hash 早就流行开来了,还不至于成为开发者之间的争论点。对于后者,客户端密码 hash 毫无作用。
chenjia404
58 天前
@CLMan #29 "可以碰撞的哈希值有 N 个,意味着破解的难度越低",这里实际上碰撞难度没有下降,还是和哈希函数的强度正相关。
CLMan
57 天前
@chenjia404 我懂你的意思了,因为 hash 函数的特点,1:N 这种对应关系,其中 N-1 个是无效值,即碰撞就是白费力气,那你的方案确实有趣。当然由于没有知识背景,我无法判断这种说法是否正确。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/956852

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX