一个抗脱库的密码哈希方法 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
这是一个专门讨论 idea 的地方。

每个人的时间,资源是有限的,有的时候你或许能够想到很多 idea,但是由于现实的限制,却并不是所有的 idea 都能够成为现实。

那这个时候,不妨可以把那些 idea 分享出来,启发别人。
chenjia404
V2EX    奇思妙想

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

  •  
  •   chenjia404 2023-07-14 19:43:56 +08:00 2919 次点击
    这是一个创建于 824 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

    31 条回复    2024-10-02 11:25:20 +08:00
    RatioPattern
        1
    RatioPattern  
       2023-07-14 21:11:42 +08:00
    直接上感觉有问题,有没有大佬解析下
    dic
        2
    dic  
       2023-07-14 21:25:08 +08:00
    直接 Bcrypt 就行了。
    dcsuibian
        3
    dcsuibian  
       2023-07-14 21:39:44 +08:00 via Android
    修改密码的时候修改用户的盐是什么意思?盐不应该就一个么
    duke807
        4
    duke807  
       2023-07-14 21:40:12 +08:00 via Android
    仅密码加网站名做 sha 运算和比对就行了
    用户名不需要
    这样不会有碰撞
    chenjia404
        5
    chenjia404  
    OP
       2023-07-14 22:48:13 +08:00
    @dcsuibian #3 每个用户一个盐,修改密码的时候就更新盐。
    chenjia404
        6
    chenjia404  
    OP
       2023-07-14 22:48:38 +08:00
    @duke807 #4 如果没有用户名,怎么确定这个哈希是这个用户呢?
    rekulas
        7
    rekulas  
       2023-07-14 22:59:39 +08:00   2
    我看了半天,你这个所谓的方案跟正常加盐 hash 没有区别

    hash(用户名+密码+网站名+盐)
    hash(密码+盐)

    如果你觉得这两个安全性不一样的话只能说明你的盐有问题
    duke807
        8
    duke807  
       2023-07-15 08:40:58 +08:00 via Android
    @chenjia404 用户名 明文 传输到服务器
    chenjia404
        9
    chenjia404  
    OP
       2023-07-15 12:32:24 +08:00
    @rekulas #7 这个没有明文密码到服务器,以及不会被彩虹表破解,用户密码不会被反向破解出来。
    googlefans
        10
    googlefans  
       2023-07-15 14:01:48 +08:00
    以后直接建内容站 直接静态
    不用数据库了
    lete
        11
    lete  
       2023-07-15 17:22:49 +08:00
    了解一下: https://unpwd.github.io , 用户直接自己加密,就连你服务器都不知道我用户的明文密码
    lucybenz
        12
    lucybenz  
       2023-07-15 21:00:10 +08:00
    说复杂了 简单讲就是做了密码字段客户端加密
    rekulas
        13
    rekulas  
       2023-07-15 21:36:49 +08:00
    @chenjia404 其实前端传输密码 hash 早就普及开了,至于破解这个只要有足够安全的盐,你在里面再加入其它别的什么难度并没有提高或降低
    chenjia404
        14
    chenjia404  
    OP
       2023-07-15 23:58:48 +08:00 via Android
    @rekulas 你没有看明白,这个方法,你没有办法反推用户密码
    dode
        15
    dode  
       2023-07-16 01:33:14 +08:00 via Android
    现在有新接口了,客户端直接使用私钥验证信息,服务器端存储每个用户设备的公钥
    8E9aYW8oj31rnbOK
        16
    8E9aYW8oj31rnbOK  
       2023-07-16 14:11:49 +08:00 via Android
    想法不错,多了一层“主观逻辑加密”
    patrickyoung
        17
    patrickyoung  
       2023-07-16 19:36:07 +08:00 via iPhone
    @chenjia404 #14 并没有没有办法这一说,只是你主观安全而已,建议系统的重学密码学。整个方案就是普通的加盐 hash
    iX8NEGGn
        18
    iX8NEGGn  
       2023-07-16 21:56:45 +08:00 via iPhone
    你这不就是把(用户名、网站名)当作盐而已嘛,还没有直接用随机的盐安全
    tt7
        19
    tt7  
       2023-07-17 00:09:57 +08:00
    @chenjia404 #9 明文密码,和没有随机数的密码 hash 有什么区别吗?
    chenjia404
        20
    chenjia404  
    OP
       2023-07-17 03:07:57 +08:00   1
    @patrickyoung #17 传统的加盐 hash ,保存了哈希和用户的对应关系,我这个没有保存用户和哈希对应关系。
    Liyuu
        21
    Liyuu  
       2023-07-17 23:36:24 +08:00
    也就是说'网站名'可以换成任意一个常量,相当于加了一个没有存在库里的盐,这样吗?
    dallaslu
        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 次
    chenjia404
        23
    chenjia404  
    OP
       2023-07-18 20:27:38 +08:00
    @dallaslu #22 旧的 auth_hash 不删除,这个表数据越多越好
    dallaslu
        24
    dallaslu  
       2023-07-19 10:44:24 +08:00
    @chenjia404 即使这个策略奏效,也只是将 256^40 变成 256^43 ,「几乎不可能」乘以十万也是「几乎不可能」
    chenjia404
        25
    chenjia404  
    OP
       2023-07-19 16:10:48 +08:00 via Android
    @dallaslu 恩,不过确实无法反向破解明文密码了,auth_hash 表公布都没有影响。
    stamhe
        26
    stamhe  
       2023-09-09 10:12:26 +08:00
    @dode 嗨,想了解一下,你这个是你们项目有在使用的东西么?
    dode
        27
    dode  
       2023-09-09 21:22:42 +08:00
    @stamhe 我们不涉及这个,我看到谷歌在用了
    stamhe
        28
    stamhe  
       2023-09-10 16:45:21 +08:00
    @dode google 和 apple 他们接入的是 fido alliance 的 passkey 方案,这个方案是个残疾。不能用于工业应用。
    CLMan
        29
    CLMan  
       2024-10-01 12:01:30 +08:00
    自从加盐哈希流行以后,安全界为啥还要建议使用 Bcrypt 、argon2 这些密码存储专用的哈希算法呢,无非是担心现有及以后的硬件暴力破解通用哈希算法太快。至于彩虹表,已经是上个过时版本了。

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

    很多人以为,密码存储哈希值是避免用户的明文密码泄露,其实不然,是避免应用的明文密码泄露。如果是前者,那客户端密码 hash 早就流行开来了,还不至于成为开发者之间的争论点。对于后者,客户端密码 hash 毫无作用。
    chenjia404
        30
    chenjia404  
    OP
       2024-10-02 03:26:33 +08:00
    @CLMan #29 "可以碰撞的哈希值有 N 个,意味着破解的难度越低",这里实际上碰撞难度没有下降,还是和哈希函数的强度正相关。
    CLMan
        31
    CLMan  
       2024-10-02 11:25:20 +08:00
    @chenjia404 我懂你的意思了,因为 hash 函数的特点,1:N 这种对应关系,其中 N-1 个是无效值,即碰撞就是白费力气,那你的方案确实有趣。当然由于没有知识背景,我无法判断这种说法是否正确。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5267 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 24ms UTC 07:18 PVG 15:18 LAX 00:18 JFK 03:18
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86