我之前做过一个方案: 哈希(用户名+密码+网站名)发送给服务器,服务器拿到提交的哈希和用户名,再哈希(用户名+密码+网站名+盐),把最后一步的哈希存在一张哈希表里面,下次用户登录的时候,只需要验证哈希表中是否有元素即可。 修改密码的时候修改用户的盐,写入新的哈希记录就行了,而且哈希表越来越大,每个网站的哈希表都不一样,泄露也没有办法跑彩虹表。 哈希函数只要是在 sha1 以上的,基本上冲突的可能性就很小。 这个方案也不需要提交明文密码到服务器,过安全测评也好过。
1
RatioPattern 2023-07-14 21:11:42 +08:00
直接上感觉有问题,有没有大佬解析下
|
2
dic 2023-07-14 21:25:08 +08:00
直接 Bcrypt 就行了。
|
3
dcsuibian 2023-07-14 21:39:44 +08:00 via Android
修改密码的时候修改用户的盐是什么意思?盐不应该就一个么
|
4
duke807 2023-07-14 21:40:12 +08:00 via Android
仅密码加网站名做 sha 运算和比对就行了
用户名不需要 这样不会有碰撞 |
5
chenjia404 OP @dcsuibian #3 每个用户一个盐,修改密码的时候就更新盐。
|
6
chenjia404 OP @duke807 #4 如果没有用户名,怎么确定这个哈希是这个用户呢?
|
7
rekulas 2023-07-14 22:59:39 +08:00 2
我看了半天,你这个所谓的方案跟正常加盐 hash 没有区别
hash(用户名+密码+网站名+盐) hash(密码+盐) 如果你觉得这两个安全性不一样的话只能说明你的盐有问题 |
8
duke807 2023-07-15 08:40:58 +08:00 via Android
@chenjia404 用户名 明文 传输到服务器
|
9
chenjia404 OP @rekulas #7 这个没有明文密码到服务器,以及不会被彩虹表破解,用户密码不会被反向破解出来。
|
10
googlefans 2023-07-15 14:01:48 +08:00
以后直接建内容站 直接静态
不用数据库了 |
11
lete 2023-07-15 17:22:49 +08:00
了解一下: https://unpwd.github.io , 用户直接自己加密,就连你服务器都不知道我用户的明文密码
|
12
lucybenz 2023-07-15 21:00:10 +08:00
说复杂了 简单讲就是做了密码字段客户端加密
|
13
rekulas 2023-07-15 21:36:49 +08:00
@chenjia404 其实前端传输密码 hash 早就普及开了,至于破解这个只要有足够安全的盐,你在里面再加入其它别的什么难度并没有提高或降低
|
14
chenjia404 OP @rekulas 你没有看明白,这个方法,你没有办法反推用户密码
|
15
dode 2023-07-16 01:33:14 +08:00 via Android
现在有新接口了,客户端直接使用私钥验证信息,服务器端存储每个用户设备的公钥
|
16
8E9aYW8oj31rnbOK 2023-07-16 14:11:49 +08:00 via Android
想法不错,多了一层“主观逻辑加密”
|
17
patrickyoung 2023-07-16 19:36:07 +08:00 via iPhone
@chenjia404 #14 并没有没有办法这一说,只是你主观安全而已,建议系统的重学密码学。整个方案就是普通的加盐 hash
|
18
iX8NEGGn 2023-07-16 21:56:45 +08:00 via iPhone
你这不就是把(用户名、网站名)当作盐而已嘛,还没有直接用随机的盐安全
|
19
tt7 2023-07-17 00:09:57 +08:00
@chenjia404 #9 明文密码,和没有随机数的密码 hash 有什么区别吗?
|
20
chenjia404 OP @patrickyoung #17 传统的加盐 hash ,保存了哈希和用户的对应关系,我这个没有保存用户和哈希对应关系。
|
21
Liyuu 2023-07-17 23:36:24 +08:00
也就是说'网站名'可以换成任意一个常量,相当于加了一个没有存在库里的盐,这样吗?
|
22
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 次 |
23
chenjia404 OP @dallaslu #22 旧的 auth_hash 不删除,这个表数据越多越好
|
24
dallaslu 2023-07-19 10:44:24 +08:00
@chenjia404 即使这个策略奏效,也只是将 256^40 变成 256^43 ,「几乎不可能」乘以十万也是「几乎不可能」
|
25
chenjia404 OP @dallaslu 恩,不过确实无法反向破解明文密码了,auth_hash 表公布都没有影响。
|
28
stamhe 2023-09-10 16:45:21 +08:00
@dode google 和 apple 他们接入的是 fido alliance 的 passkey 方案,这个方案是个残疾。不能用于工业应用。
|
29
CLMan 53 天前
自从加盐哈希流行以后,安全界为啥还要建议使用 Bcrypt 、argon2 这些密码存储专用的哈希算法呢,无非是担心现有及以后的硬件暴力破解通用哈希算法太快。至于彩虹表,已经是上个过时版本了。
而你认为设计很好的点“ auth_hash 与 user 并非一一对应”,反而是最大的漏洞,因为它们其实是 N:1 的关系( N 指 auth_hash 表的大小),意味着暴力破解时,可以碰撞的哈希值有 N 个。“这个表数据越多越好”,意味着破解的难度越低。 很多人以为,密码存储哈希值是避免用户的明文密码泄露,其实不然,是避免应用的明文密码泄露。如果是前者,那客户端密码 hash 早就流行开来了,还不至于成为开发者之间的争论点。对于后者,客户端密码 hash 毫无作用。 |
30
chenjia404 OP @CLMan #29 "可以碰撞的哈希值有 N 个,意味着破解的难度越低",这里实际上碰撞难度没有下降,还是和哈希函数的强度正相关。
|
31
CLMan 52 天前
@chenjia404 我懂你的意思了,因为 hash 函数的特点,1:N 这种对应关系,其中 N-1 个是无效值,即碰撞就是白费力气,那你的方案确实有趣。当然由于没有知识背景,我无法判断这种说法是否正确。
|