V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
iqoo
V2EX  ›  程序员

别再纠结前端要不要提交明文口令,浏览器已经内置非常好的方案

  •  1
     
  •   iqoo · 180 天前 · 11020 次点击
    这是一个创建于 180 天前的主题,其中的信息可能已经有所发展或是发生改变。

    这个十年前就有结论的问题每隔一段时间都会有人讨论。结论是不管什么环境,前端提交 hash 后的口令总是好的,防的不是中途的嗅探者,而是脱库后的破解者。前端 hash 越耗时,脱库后跑字典越慢。

    至于前端 hash 也不用自己捣鼓 js/wasm 这些,主流浏览器早已内置 PBKDF2 算法,较新的 CPU 都有相应的硬件加速,比自己实现可以快很多倍。

    演示:

    const username = new TextEncoder().encode('alice')
    const password = new TextEncoder().encode('hello1234')
    
    // 重复 1000 万次 SHA256
    const pbkdfOpts = {
      name: 'PBKDF2',
      hash: 'SHA-256',
      salt: username,
      iterations: 1e7,
    }
    
    async function pbkdf2(pwd, opts, bits) {
      const baseKey = await crypto.subtle.importKey('raw', pwd, 'PBKDF2', false, ['deriveBits'])
      const buf = await crypto.subtle.deriveBits(opts, baseKey, bits)
      return new Uint8Array(buf)
    }
    
    const dk = await pbkdf2(password, pbkdfOpts, 256)
    
    // 注册/登录提交 dk 即可,无需提交 password
    console.log(dk)
    
    
    第 1 条附言  ·  180 天前

    1000 万次 SHA256 在近几年的 CPU 上大约 1s,可以参考之前帖子 发一个拼 CPU 性能的红包。如果要兼顾低端设备可以调低点,也可以注册时让用户自己选(或者自动选)常用设备的性能。

    如果觉得 1s 太久但又不想降低强度,可以同时异步算多个 PBKDF2,每个参数不同(比如 salt 加个后缀),然后把结果合并即可。破解难度相当于乘上了线程数。

    第 2 条附言  ·  180 天前

    修改下:

    如果觉得强度不够但又不想增加时间,可以同时异步算多个 PBKDF2,每个参数不同(比如 salt 加个后缀),然后把各个 dk 合并后再 hash 出一个结果即可。破解难度相当于乘上了线程数。

    第 3 条附言  ·  180 天前
    顺便分享一个利用多线程的 PBKDF2 演示: https://etherdream.github.io/parallel-pbkdf2/
    93 条回复    2024-05-28 11:59:06 +08:00
    lisxour
        1
    lisxour  
       180 天前
    你强任你强,md5 一把梭
    passon
        2
    passon  
       180 天前   ❤️ 1
    @lisxour md5 公司已经不让用在密码场景了
    LandCruiser
        3
    LandCruiser  
       180 天前   ❤️ 15
    前端明文提,后端就要铭文存?什么逻辑啊。。。
    majula
        4
    majula  
       180 天前
    可以了解一下 PAKE ,比传统的 KDF 泄露密码的风险更低。

    我们公司网站目前用的是 OPAQUE: https://www.ietf.org/archive/id/draft-irtf-cfrg-opaque-02.html
    iqoo
        5
    iqoo  
    OP
       180 天前
    @LandCruiser KDF 计算量太大,后端算成本太高。
    beginor
        6
    beginor  
       180 天前
    iqoo
        7
    iqoo  
    OP
       180 天前
    @beginor 支持的,演示代码可以跑。不过 FireFox 没有加速,比 chrome 慢一倍。
    tool2dx
        8
    tool2dx  
       180 天前
    iterations: 1e7, 那么大的递归数值?绝了,确实普通 PC 没办法轻易破解。

    就是怕老 arm 手机浏览器,会算不过来。
    HojiOShi
        9
    HojiOShi  
       180 天前
    @beginor #6 我用 Firefox 125 跑上面的 demo 没问题啊,生成结果也和 Chrome 一致。
    StevenRCE0
        10
    StevenRCE0  
       180 天前
    谢谢科普,马了
    Chad0000
        11
    Chad0000  
       180 天前   ❤️ 8
    不管你怎么算的,都可以将算的结果认为是“密码”,服务端认这个“密码”就得。

    当天强度不够了,要升级:服务端没办法认新的算法了吧?必须得强迫用户重置密码?
    kdwnil
        12
    kdwnil  
       180 天前
    道理我都懂,但是

    > Crypto.subtle
    > 安全上下文: 此项功能仅在一些支持的浏览器的安全上下文( HTTPS )中可用。

    而更有必要倒腾前端加密的 http 页面被完全排除在外,另外一般脱库得到的是加密后的 hash ,也没法拿去撞库吧
    Puteulanus
        13
    Puteulanus  
       180 天前   ❤️ 4
    后端用慢 hash 来增加密文泄漏时候的暴力破解成本,但是用户量大了的话后端自己很难扛住这么大量的慢 hash 计算量,所以把计算过程分到前端去做,本质上不是为了安全(虽然后端上慢 hash 确实是为了安全),而是一种分布式计算的方案
    GaGaGood
        14
    GaGaGood  
       180 天前 via iPhone
    @Chad0000 同疑问
    iqoo
        15
    iqoo  
    OP
       180 天前
    @Chad0000 其实是重置“强度”,口令本身不用改。后端要求升级时,用户登录时把旧的 KDF 和新的 KDF 都提交上去,旧的用于验证,新的用于更新。
    Chad0000
        16
    Chad0000  
       180 天前
    @iqoo #15
    假如有 N 个版本呢?还得记录每次用户的密码?或者 N 个版本所有终端不能同时升级到最新版,那么有的旧版的终端怎么办?
    lovelylain
        17
    lovelylain  
       180 天前 via Android
    我觉得还是不 hash 更好,用非对称加密传输。
    10 年前前端 hash 用的是 md5 ,现在认为 md5 不安全,你只能把 md5 当原始密码再做一次新 hash ,要是未来新 hash 算法也被认为不安全,你是不是要再套一层?
    前端传可解密的密文,更能适应技术升级,未来你 db 用的 hash 算法被认为不安全了,也可以在用户重新登录时更换新的 hash 算法。而前端传 hash ,未来前端技术升级,你要把 hash 当密码,要么同时传可解密密码和 hash ,反正原 hash 是甩不掉了。
    chingyat
        18
    chingyat  
       180 天前 via iPhone
    @Chad0000 不太会有多个版本吧,hash 算法更新换代没那么快
    Chad0000
        19
    Chad0000  
       180 天前
    @chingyat #18
    就算没有多个版本,你现在需要升级算法。但:你有网页版和 APP 版,前者容易,后者你都不一定能限定用户必须使用某个版本的 APP 。你直接停掉之前所有版本的 APP 强迫用户升级?还是你做兼容(意味着保存多个密码版本)?
    iminto
        20
    iminto  
       180 天前 via Android
    看得我一头雾水,我是不是穿越了?

    16 年前,人人网最红火的年代,就看过有人研究人人网的爬虫,它的登录就是用的 RSA 算法做加密的。现在都 2024 了,还有人讨论这类的问题吗?

    至于有一层楼 @majula 提到的 PAKE 算法,怎么看着像是币圈造的轮子呢?
    zictos
        21
    zictos  
       180 天前
    先 sha256 ,如果还不行就加时间戳再 sha256 一次,时间戳也作为参数传输
    iqoo
        22
    iqoo  
    OP
       180 天前
    @Chad0000 记录每个用户的难度值就可以了(这个值公开)。登录时输完用户名,前端可以得到当前难度值。然后算这个难度值的 dk 。如果后端还给了新的难度值,顺便再算新的 dk 。
    Chad0000
        23
    Chad0000  
       180 天前
    @iqoo #22

    又多一个难度值的概念,请问你做了这么多操作,将安全提升了多少?有 100%提升还是 1%还不到?
    iqoo
        24
    iqoo  
    OP
       180 天前
    @Chad0000 难度值本身就有,代码里那个 1000 万。你说要考虑后期升级,才出现这么多操作。最简单就是用固定的值。
    Chad0000
        25
    Chad0000  
       180 天前
    @iqoo #24

    那你的方案会带来密码碎片化:只要无法做到所有终端一起升级,服务器就不得不使用原密码将每种 Hash 都算一遍保存起来,否则还没来得及升级的终端的登录将无法得到验证。
    Chad0000
        26
    Chad0000  
       180 天前
    @iqoo #24

    或者,你的方案本来执行得好好的,哪天老板脑子抽筋说某个穿戴设备也需要对接。

    手表上跑 1000 万次 Sha256 ,额。
    iqoo
        27
    iqoo  
    OP
       180 天前   ❤️ 1
    @Chad0000 不会有碎片化。保存的只有当前难度值和对应的 hash 。客户端升级的时候需要用户重新输入一次密码。升级难度也不会很频繁,可能几年才一次。
    iqoo
        28
    iqoo  
    OP
       180 天前
    @Chad0000 低端设备确实没办法😂 不过穿戴设备也不方便输入,可以直接在手机或电脑上登录,把登录态同步过来。或者通过扫描等方式把 dk 同步过来。
    shiny
        29
    shiny  
       180 天前
    前端能 hash ,后端也能 hash
    大多数情况下脱库都是查彩虹表,这种场景下一个靠谱的 hash 才是关键,而不是在哪一端 hash 的。
    Chad0000
        30
    Chad0000  
       180 天前
    @iqoo #27
    你没明白我说的,我说的就是升级的时候发生的事情:只要你没办法统一升级客户端(让他们一致使用新的难度),你就得保存难度的 Hash 过后的密码,否则其他难度的登录请求你没办法验证。
    iqoo
        31
    iqoo  
    OP
       180 天前
    @shiny hash 和 PBKDF 还是有区别的,这个强度的 PBKDF 彩虹表得几十年吧。
    tool2dx
        32
    tool2dx  
       180 天前   ❤️ 1
    这算法自古以来就有,早在 linux 还叫 unix 年代,password 就为了防止本地账号密码破解,启用了递归 hash 算法,那时候是 md5 递归 1000 次,代码里还专门注明了一句:just to make sure things don't run too fast 。
    mark2025
        33
    mark2025  
       180 天前
    PBKDF2 挺不错的,基本是通用口令散列算法了
    shiny
        34
    shiny  
       180 天前
    @iqoo 这也是种 hash 算法,所以我说选个靠谱的 hash 算法……
    iqoo
        35
    iqoo  
    OP
       180 天前
    @Chad0000 难度值可以不用写死在客户端,可以通过用户名实时查询,是公开的。(这个值也没有太大的隐私性)
    iqoo
        36
    iqoo  
    OP
       180 天前
    @shiny 目前浏览器里只有 sha 相关的 pbkdf ,只能在 salt 上做些变通,比如选取 网站 uuid+用户名,专为这个网站做彩虹表,成本太大划不来。
    Chad0000
        37
    Chad0000  
       180 天前
    @iqoo #35

    用户名可以被扫描了:安全值 - 1 。

    另,哪天 Sha256 不安全了,你需要换个算法,你一样会遇到上述问题。你为了避免被脱库,将算法固化在了前端,导致后期修改比较复杂,这个算是得不偿失的方案。
    drymonfidelia
        38
    drymonfidelia  
       180 天前 via iPhone
    @iqoo 穿戴设备也不方便输入:老板说别人都可以,我们不行就是你不专业
    tool2dx
        39
    tool2dx  
       180 天前
    @Chad0000 没有固化,现在的 hash 和以前的 hash 不一样了,都是加密码的。

    比如 wireguard 协议,里面用的是 blake2s 算法,和 OP 这个类似,你密码一变,hash 结果天差地别。
    forvvvv123
        40
    forvvvv123  
       180 天前
    @lovelylain

    感觉不好搞吧,前端 RSA 或者 ECC 把密码密文传过来,后端解成明文后 hash 再跟库里的 hash 对比吗? 这样其实后端开发能知道用户所有明文密码
    Chad0000
        41
    Chad0000  
       180 天前
    @tool2dx #39
    “现在的 hash 和以前的 hash 不一样了"

    你看吧,Hash 也有新算法,也就是说你永远没办法保证现在的 Hash 算法就是最佳的:这就意味着哪天你会需要升级前端算法以保证安全(不会被迅速脱库)。又回到我上面说的:如何确保不同终端一并更新,而且你的新算法还得考虑到不同算力的终端(从 PC 到手机再到穿戴设备)。而且你的前端算法还是公开的。

    所以,为什么不定期更新后端密码落库的算法呢?这个百分百可控,不影响前端,任你随便玩,你还可以将应用和 DB 分开,这样只拿到 DB 不知道应用里的参数(比如这个 1000 万次 Hash ),是没办法彩虹的。不更好么?
    iqoo
        42
    iqoo  
    OP
       180 天前   ❤️ 1
    @Chad0000 这个是可以缓解的,不管用户存不存在,都可以返回一个值。

    实际应用时为了灵活性,返回的并不是难度值,而是算法名和参数,这样适用于任何算法。

    (更进一步,比如针对浏览器的场合,返回的甚至是一个 JS 版本号,前端动态加载这个 JS ,然后通过约定的接口去计算 hash 。顺便还可以在动态模块里做些风控检测)
    Chad0000
        43
    Chad0000  
       180 天前
    @iqoo #42
    那问题可就多了去了,不同终端还得适配不对算法:我桌面软件不是 Jscript 写的怎么办?手表也不可能是 JS 写的,要动态加载 JS ?

    如何确保这个 JS 是安全的,万一被别人替换了或开发不小心搞错配置文件直接改明文了。你返回算法名,如果我旧的终端当时还没有这种新的算法呢?那你得提前更新新算法到终端,否则终端不支持。

    还是回到那句话:你做了这么复杂的方案,安全提升了(或降低)几个百分点?是否值得?
    treblex
        44
    treblex  
       180 天前
    @Chad0000 #16 django 是这样支持不同的加密后端的,当然我也是不支持在前端搞这个的
    tool2dx
        45
    tool2dx  
       180 天前   ❤️ 2
    我简单科普一下,可能有些新人不了解 PBKDF2

    一个 hash 函数,比如 sha256 为了防止被破解,需要加入密码,起名为 HMAC 。

    而 PBKDF2 ,就是针对于 HMAC 递归计算,次数就是 OP 里的 1000 万次,计算量的增加,大大加强了 HMAC 的安全性。

    而网页登陆的用户名,就是 hash 函数的密码(也叫 salt)

    这样做有什么好处呢,那就是针对用户名 A 建立的彩虹表,无法用于用户名 B/C/D 。不同用户名只能单独计算,这就增加了密码防撞的安全性。
    iqoo
        46
    iqoo  
    OP
       180 天前
    @Chad0000 这个方案只讨论针对浏览器的场合,本身就是一个低成本方案,也没考虑要升级难度。多加几行代码,多花几百 ms 强化口令,用 dk 代替 password 而已,没有非常大的提升但聊胜于无。
    rxmt
        47
    rxmt  
       180 天前
    前几天刷到好几个明文密码帖子,我没有仔细研究过密码传输,正在看各个帖子里的观点。
    ---

    我有一个想法,如果非对称加密传输可以么?不这样做的原因是开销太大吗?
    Chad0000
        48
    Chad0000  
       180 天前   ❤️ 2
    @rxmt #47
    有人问得好,安全要看你防的谁。

    非对称你是要防传输层:
    - 人家大可以给你一个假的密钥:你可以做证书认证 - 恭喜你发明了 HTTPS
    - 传输层大可以直接换掉你的 JS 文件,跳过加密算法不更简单么
    rxmt
        49
    rxmt  
       180 天前
    @Chad0000 我有一个十几个人用的工具是这么干的:
    前端公钥加密 -> 后端解密 -> 对比鉴权

    好像这样做没有跳过加密的问题,但是好像完全不在乎开销= =

    系统学学这块好像还挺有意思
    zhtyytg
        50
    zhtyytg  
       180 天前   ❤️ 1
    @rxmt 是没有必要,前端加密对于本地用户仅仅只是增加了破解难度,对于中间人攻击则 https 就可以防御,对于后端来说如果拿到即存数据库则密码是不安全的所以后端往往会在存储前再处理一次(不可逆 hash)。所以前端加密的意义在资深前端看来仅仅起到防脚本小子和呆比,类比前端代码混淆
    gamexg
        51
    gamexg  
       180 天前   ❤️ 1
    @rxmt #47 因为 https 已经实现了非对称加密握手+对称加密传输.
    自己再做一层没必要,而且还不如 https 实现可靠,至少 https 还有个根证书机构认证公钥.
    gamexg
        52
    gamexg  
       180 天前   ❤️ 1
    我没理解错误的话,
    这个的作用是把用户长度不一,特殊字符不一的密码统一变成了 17EB4014C8C461C300E9B61518B9A18B 固定长度固定格式的密码?

    攻击者也不需要知道用户原始密码,攻击者只要拿到这个加密后的密码就能当作真正的密码来实现登录.


    另外,对于防止脱裤后的破解者,靠谱的解决办法不是每个用户用不同的随机盐吗?
    随机盐可以使得本来一个彩虹表就能解决的问题变成每个用户都要有一个彩虹表,直接造成彩虹表无效,破解难度爆表.
    Y25tIGxpdmlk
        53
    Y25tIGxpdmlk  
       180 天前   ❤️ 2
    @iqoo #5 你的网站注册、登陆这类提交密码的操作并发很高吗??
    gamexg
        54
    gamexg  
       180 天前
    @gamexg #48 不过考虑到现在基本都使用了 CDN,然后 CDN 处都有 https 证书,CDN 可以得到密码.
    可能还真需要自己再套一层加密机制,或者登陆相关的域名不经过 CDN,
    tool2dx
        55
    tool2dx  
       180 天前
    @gamexg 是加盐啊,但是传统加随机盐,一个用户算起来还是太快了。

    而 OP 的默认算法,一个用户在我机器上最起码要 3 秒才出结果,实在是够慢的。
    dode
        56
    dode  
       180 天前
    正经的服务器都不是明文存储用户密码,比如谷歌。

    你这每次认证算一个密码 hash 出来,提交到服务器,服务器没法知道你的密码对不对?
    dode
        57
    dode  
       180 天前
    演示程序电脑上跑了 5 秒
    DeWjjj
        58
    DeWjjj  
       180 天前
    后端存密码加的盐越多,密码就越安全,不过事实上没什么用。
    现在基本靠二次验证做保护,账户内消费靠二级密码。
    dode
        59
    dode  
       180 天前   ❤️ 1
    正经的安全是浏览器&密码管理器在每个网站密码框自动生成填充一个唯一密码
    Chad0000
        60
    Chad0000  
       180 天前
    @gamexg #54
    其实没用,对于 CDN 来说,这个 Hash 过的密码也是密码,直接发给后端一样能登录。


    @tool2dx #55
    后端还可以将盐的算法跟用户名+版本号相关,这样有盐但不需要保存盐,只脱库没拿到应用的算法,破解者都不知道盐是什么(甚至盐会参与源密码进一步混淆),加大脱库难度。
    danhahaha
        61
    danhahaha  
       180 天前
    前后端纠结于各种算法的安全性,用户依旧 123456 走天下
    dode
        62
    dode  
       180 天前
    @gamexg
    CDN 理论上可以直接修改你的网站内全部东西,比如给密码输入框增加一个密码收集函数

    @iqoo
    你这前端有一个通用接口查询用户难度,岂不是泄漏用户名称,导致用户 ID 被暴力爬取,脱库
    gamexg
        63
    gamexg  
       180 天前
    @Chad0000 #60 我回复错了, 回复的 @rxmt .
    不是用 hash ,而是直接自己再实现个公钥加密,来防止 CDN 处有问题造成泄露密码.

    国内不知道,我是知道国外一些机房管理混乱程度.
    以前公司的租的物理机被入侵了,
    排查日志发现,被人用机房的账号登录了 ipmi ,重启服务器添加账号实现的入侵.
    还是比较大的机房,全球都有机房的....
    gamexg
        64
    gamexg  
       180 天前
    @dode #62 添加密码手机函数被发现的风险就大得多了.
    我是觉得非针对单个网站,广谱的密码收集工具还是监听方式实现更不容易被发现.

    当然真的被专门针对的话那就只能说认了,
    即使将登陆相关的改为独立子域名不经过 CDN,但是 CDN 还是能够利用经过的域名获得 cookie .
    甚至将登录域名改为经过 CDN 的域名.
    knva
        65
    knva  
       180 天前
    纠结这个不如让用户来个 16 位以上大小写特殊符号密码
    forty
        66
    forty  
       180 天前
    1. 要防 CDN ,那就自己再来一层公钥加密。
    2. 要兼顾多版本客户端:
    2.1 在客户端提交请求时,附带客户端版本号,以便后端识别后区别采用新旧算法
    2.2 或在新旧客户端都保持长期固定不变的算法。

    至于说要后端保存每种不同 hash 值的,完全不需要。
    Chad0000
        67
    Chad0000  
       180 天前 via iPhone
    @forty #66
    “ 至于说要后端保存每种不同 hash 值的,完全不需要”

    要不你再仔细想想?当然如果你说只限 web 当我没说。
    DesnLee
        68
    DesnLee  
       180 天前
    没看到有人讨论 bcrypt 呢
    sampeng
        69
    sampeng  
       180 天前
    我一直奇怪这有啥好讨论的。。。。
    forty
        70
    forty  
       180 天前
    @Chad0000 web 也是个客户端,跟别的客户端没有本质区别
    liuzhaowei55
        71
    liuzhaowei55  
       180 天前 via Android
    pbkdf2 在动态 salt 的情况下才有意义吧
    zhzbql
        72
    zhzbql  
       180 天前
    花里胡哨的不如强制密码长度增加 2 个字符
    supuwoerc
        73
    supuwoerc  
       180 天前
    我用的 bcrypt...
    fionasit007
        74
    fionasit007  
       180 天前
    说得好,实操还是 md5 一把梭
    forty
        75
    forty  
       180 天前
    @zhzbql 直接来短信验证码,或 2FA ,省事了。
    Chad0000
        76
    Chad0000  
       180 天前 via iPhone
    @forty #70
    在是否能及时更新(算法)这个方面有很大区别。
    forty
        77
    forty  
       180 天前
    @Chad0000 当然能及时更新,前面已经有兄弟说了,就是支持多种算法的。
    Chad0000
        78
    Chad0000  
       180 天前 via iPhone
    @forty
    完全换另外一个算法的话,你就需要提前部署那个算法。否则 app 来不及适配,尤其是紧急安全事件,你得有足够窗口期提前安排。还是那句,搞这么复杂到底提升了多少安全性。
    forty
        79
    forty  
       180 天前
    @Chad0000 你说的“紧急安全事件”是指某个哈希算法不安全了吗?这种不会紧急。一般紧急都是数据库或某些算法泄露吧,这种就换后端算法啊。 客户端算法就保持不变,固定一套基本的哈希就够了,可变部分由服务端来提供。

    你说的“搞这么复杂”不知道所指是哪个方案,是指 OP 的那个吗?我其实并不认同 OP 方案。

    不复杂,也可以实现我说的:

    [ [
    1. 要防 CDN ,那就自己再来一层公钥加密。
    2. 要兼顾多版本客户端:
    -- 2.1 在客户端提交请求时,附带客户端版本号,以便后端识别后区别采用新旧算法
    -- 2.2 或在新旧客户端都保持长期固定不变的哈希算法。(算法不变,但是参数会变,结果会变)

    至于说要后端保存每种不同 hash 值的,完全不需要。
    ] ]
    expy
        80
    expy  
       180 天前
    前端 hash 后,数据库是直接存前端的 hash ,还是用 argon2 之类专用算法再 hash 一次?
    yjhatfdu2
        81
    yjhatfdu2  
       180 天前   ❤️ 1
    我感觉很多人既不懂加密、又不懂安全、又没有逻辑,楼主还是很懂的
    gavin810
        82
    gavin810  
       180 天前
    我在做一个比较小的项目的时候,鉴权设计主要是听甲方的——前后端都得 hash 。
    但我个人觉得觉得前端大多数情况下都没有必要做 hash ,https 和后端的加密就已经足够了。哲学上有个概念,奥卡姆剃刀原理,如无必要,勿增实体。代码设计上也有一种思想,worse is better ,我感觉有点不谋而合。

    绝对的安全是很难保证的。

    毕竟自己的网站设置再复杂的 hash 函数,迭代的次数再多,加再多的盐,也很难防止用户自己泄露或者其他网站的密码库泄露。不是所有人都会对每个网站设不同的用户名密码,也不是所有网站的安全性都很高,或者有些无良网站干脆就存明文。
    在这种情况下,前端加 hash 唯一能提供的,就是开发人员给自己的一些合理的技术安慰,在泄密时保护了自己网站的密码,虽然这总归是好的。

    所以加或者不加,很大程度上取决于你的需求。

    参考《加盐 hash 保存密码的正确方式.md
    https://github.com/su18/wooyun-drops/blob/b2a5416/papers/%E5%8A%A0%E7%9B%90hash%E4%BF%9D%E5%AD%98%E5%AF%86%E7%A0%81%E7%9A%84%E6%AD%A3%E7%A1%AE%E6%96%B9%E5%BC%8F.md
    fly2never
        83
    fly2never  
       180 天前
    如果有跨平台的 c++库(比如 openssl)支持还行, 很多 api 需要 多端调用, 用 c++开发复用才能做到最大范围覆盖
    forgottencoast
        84
    forgottencoast  
       180 天前
    @danhahaha
    现在只要稍微有点良心的网站都不会允许纯数字的密码,别说 123456 了。
    BeautifulSoap
        85
    BeautifulSoap  
       180 天前 via Android
    看了这么多觉得前段 hash 是极有必要安全非常非常多的人的言论,我有一种感觉,是不是觉得前端 hash 有必要的基本都是前端工程师

    要不然怎么会出现如此奇怪的在完全不相信后端的同时,又同时完全相信同一个公司做出的网页前端?
    hesetiema
        86
    hesetiema  
       180 天前
    用 wasm 代替 js 做 hash 或者加密,是不是更好呢...
    restkhz
        87
    restkhz  
       180 天前
    黑客看到普通登录框,没验证码:先上 burp 爆破
    黑客看到楼主登录框,没验证码:咦?这个 burp 好像跑不了。(看源码) md 这个人怎么实现登录都搞这么 xxx 复杂!不搞了! burp 关闭!

    黑客看到 md5: 查查 cmd5 ,没有?字典跑跑。还没有?算了。(他甚至没注意你有没有加盐)
    黑客看到 bcrypt: 字典跑跑(五分钟以后)admin123

    楼主你的安全不是因为你 hash 方法牛逼防止拖库后被破解,
    而是实现方法足够复杂直接让黑客从开始就放弃。
    退敌于千里,治病于腠理。实在是高!

    底下讨论:
    有些人正在重新发明 TLS ,
    有些人说一些有的没的,
    只有 Chad0000 在努力证明楼主这样做不值得。

    实话说,我也觉得没必要。但是想想也不是不行,理由如上。
    hesetiema
        88
    hesetiema  
       180 天前
    Chad0000
        89
    Chad0000  
       179 天前
    @restkhz #87
    我理解 OP 想避免被脱库,但增加脱库难度有很多方案,OP 偏偏选了一种“御敌 999 ,自损 300”的做法。我上面的说法就是在说这种自损是否值得。就没更好更优雅的方案了么?当然有啊,其中之一就是脱库者都不知道加密方式(未拿到软件系统),盐也不在 DB 中(算出来的),每个用户加密会根据用户本身信息而变(比如用户密码版本号),那对脱库的也是一种打击。
    xuanbg
        90
    xuanbg  
       179 天前
    随便加个盐或 2 次 md5 彩虹表就废了,密码传输的安全性早有定论,不明白这种问题为何还成了月经贴
    ZhiyuanLin
        91
    ZhiyuanLin  
       179 天前
    2024 年了,可以用 Passkey 。
    别瞎折腾密码了。
    baobao1270
        92
    baobao1270  
       179 天前
    1. crypto.subtle 这个 API 其实出现很久了,但是主流的厂商并没有使用。我也不知道为啥,反正我是用了。具体的兼容性可以看 https://caniuse.com/cryptography

    2. 这个 API 既有哈希算法,又有非对称/对称加密算法。个人其实还是推荐前端做 RSA 加密而不是直接把哈希给后端。这么做有两个原因:一是盐始终应该在服务器端随机生成且客户端不可知(这就排除了客户端生成或者使用用户名做盐的做法);二是处于业务的需要,服务器是有必要知道用户的明文密码的,场景包括:
    a. 在后端也应该过一遍密码强度检查,不可以直接信任用户的输入
    b. 对常见易猜或已知泄露的密码进行检测并提示用户
    c. 对密码进行敏感检查(我也不知道为啥有这个需求,但是新浪一直有这个机制)
    d. 过滤密码中的不可显示字符和非 ASCII 字符(我是认为应该禁止用户使用非 ASCII 字符作为密码的——虽然会牺牲一定安全性,但是从业务的角度考虑,如果用户在一个设备上不小心输入了什么奇怪的字符、在另一个设备上输不进去了,搞不好会怪你——说到底还是业务和安全的 trade-off )

    3. 哈希算法的话,也是 argon2id 优于 PBKDF2 ,只是前者没有 FIPS 认证,对于需要安全认证的业务还是只能用 PBKDF2 。
    mark2025
        93
    mark2025  
       179 天前
    @gamexg 这是入库的对于明文口令摘要的密文口令,如果被拖库或者其它方式拿到这个值,的确可以直接登录的。但这儿摘要的目的是避免通过这个密文解算出用户的明文口令,然后拿到其它网站去入侵。
    而实际用户在登录的时候是输入明文口令算出密文口令,然后拿服务器给出的随机盐再做一次散列。服务器拿到后用数据库保存的密文口令通过相同算法计算出的值去比较。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1630 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 16:56 · PVG 00:56 · LAX 08:56 · JFK 11:56
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.