@
Buges 如果把「认证要素」(无论是 plain password 还是 access token )视为 knowledge ,后端是无论如何必须知情的。后端不可能在不接触 auth chellenge 的情况下给出判定,因此「认证要素」是必须放在客户端信道中传输的。
换句话说,假如信道不安全,无论密码有无实现 hash ,中间人总是能复制出一个后端无法分辨的 chellenge 。chellenge 内容是 plain text 还是 hash 根本不重要,中间人能完整复制且通过后端验证。这是信道安全的必要性。
然后再讲充分性,即是否「只要信道安全则认证安全」;可以用其逆否来判断,即是否「认证不安全一定说明是信道不安全」。我们会发现存在比如「用户泄露自己的凭证」这种条件,所以仅当「泄露凭证」等条件不成立时才可以认为信道安全是认证安全的充分条件。(我暂时没想到其它条件,因此所有下文提到的「凭证泄露」条件都是此处反例条件的 并集,这个并集暂时只有一个元素。)
因此引理 1: auth 的安全性取决于信道安全,当且仅当凭证未泄露
第二步,我们讨论这个系统在任意情况下是否会导致凭证泄露。很容易会发现假若凭证存储等于凭证原文时凭证有可能泄露,而当凭证存储不完全独立于其它关联信息时(比如用户个人信息),也有导致泄露的可能性,其余情况不可能泄露。
因此引理 2: 当且仅当凭证存储的内容完全独立于关联性数据,且无法根据存储还原出凭证原文时,「凭证泄露」不可能发生
看这两个引理:
1. 当凭证不泄露时信道安全是认证安全的充要条件
2. 当凭证存储于原文和相关信息都完全独立时凭证不可能泄露
我们可以得出结论: 只要传输的认证要素与用户相关信息完全独立且信道是安全的,那么认证就是安全的。
用密码的一大问题是它跟用户信息往往存在相关性,因此使用密码原文作为认证要素有泄露密码的风险。但注意这不是因为脱库能拖出密码,也不是因为密码被撞了。我们现在讨论的是单一系统的安全性。是在说如果库记录完全公开了,这个用户的密码是否有被还原的可能性。如果他的密码本身就非常随机,即使库被公开了,密码也是不可能泄露的(不考虑 hash 被爆破的可能性)。
再强调一下,至此为止我们只考虑单一系统的安全性,不考 hash 能从已知明文撞出来的情况。
然后第三步,我们才来考虑多个这样的系统同时存在的场景。很容易发现由于引理 2 ,只要两个系统存在同样的密文,那么这两个系统就有可能发生相互泄露,因为此时「另一个库的密文」就是「本库密文」的相关数据了。换言之如果一个库存储的凭证被泄露了,是有可能发生另一个库的凭证泄露,从而破坏另一个系统的认证安全的。不过在单系统场景的假设下,凭证是可以不存在泄露可能的,即使凭证可以从一个系统泄露到另一个系统,但第一个泄露本身不可能发生。
综上总结一下我在实行和可得出结论的:
1. 前端加密没有用,因为它不增加信道安全性。顶多增加凭证密文的独立性,但假如我密码足够随机,在可信信道中传递密码还是 hash 过的密码有什么所谓呢
2. 多系统共用密码且共用了 hash 方法的话很可能会发生撞库,但只要保证每个这种系统即使数据库公开也无法还原我的密码,那我大可以就只用一个密码,想撞库,没材料。
3. 所以我现在的密码是分级的
- 垃圾不信任级:我感觉这网站的密码没准是明文存的,那么避免使用密码,只使用 otp 如短信验证码这种认证方式。因为对于这些网站来说密码根本是冗余的、无效的认证信息。
- 可信级,我觉得这网站的密码存储机制是足够科学的,即使库爆了应该也不能还原出密码。这些网站我全都使用同样的随机密码,因为记随机密码的心智负担有点大,我只能记一两个
- 高安全等级,存了我大量个人信息和记录的,绝对要杜绝任何认证被攻破可能性的,比如 google qq 这种,每个网站使用完全不同的密码,我有一套生成规则
4. 我不使用密码管理器。因为无非是把撞库风险面从远程服务器转到了个人设备上。而个人设备很容易使人掉以轻心,比如相信不少人密码管理器的 pin 就不会很复杂了对吧
5. 开发要登录的业务系统,不进行任何传输层上的变形,比如什么前端 hash 这种,没用。when in need 套 TLS