一些(尤其是银行)密码系统要求您从密码中输入三个(指定的)字母才能登录。这应该可以击败键盘记录器,并可能会破坏线路嗅探重放攻击(对于未加密的会话)。
显然,这种方案无法使用普通的密码散列来工作,因为您需要知道整个密码才能计算散列。
这样的系统通常在服务器端存储什么来完成这项工作?
他们是否以明文形式存储密码,或者每个字母的单独哈希值,还是什么?
正如您正确指出的那样,如果仅使用密码的子字符串完成身份验证,则标准密码哈希方案将不起作用。有多种方法可以实现这样的系统:
以明文形式存储密码:
存储密码加密,解密查看:
存储所有(或足够多)可能的子字符串的哈希值:
最终,如果数据库受到破坏,所有这些方案都会遭受暴力攻击的弱点。造成这种情况的根本原因是,在一个典型密码(或者,实际上,甚至是一个特别强的密码)的三字母子串中没有太多的熵,所以不需要很多猜测就可以破解。
这些中哪个最好?这很难说。如果我必须选择其中一种方案,我可能会选择使用强对称加密(例如 AES)的加密存储,并使用单独的服务器或 HSM 来处理加密和验证。这样,至少,破坏前端服务器的攻击者将无法仅复制数据库并离线攻击它(尽管如果 HSM 没有实施有效的速率限制,他们仍然可以对 HSM 发起暴力攻击)。
但是,我要说的是,仅使用部分密码进行身份验证的整个想法存在严重缺陷:它并没有真正提供应有的安全优势,除非在一些特别受限的攻击场景中(例如窃听者只能观察一个身份验证事件,并且不能一直尝试直到他们得到相同的挑战),但它通过减少成功身份验证所需的信息量从根本上削弱了安全性。对于部分密码身份验证应该解决的安全问题,有更好的解决方案,例如TAN 。