为了验证最终用户对某些信息资源的访问权限,有几个问题要求输入关于存储(可能加盐)用户名哈希的智慧。我看到的大多数答案都非常反对这个想法,但没有一个解决了这种方法可能会缓解的漏洞。
我指的漏洞是用户名/密码重用。许多最近的数据库泄露导致发布明文用户名和相关密码(如果开发人员没有先散列)或密码散列(可能已经或可能没有加盐)。
所以我的问题是,存储散列用户名是否会使用特定于站点的秘密值加盐(除了正确存储加盐和散列密码),是否会减轻用户名/密码重用的漏洞?当然,这不能防止从以前被入侵的站点重复使用的用户名/密码对。这个问题主要是指通过不成为这种妥协的来源来保护用户信息的想法。
更新:似乎有很多关于如何实施的问题。这是我为构建的 MySQL 数据库所采用的方法的简要概述。它缺少所有细节,并且可能有一些我没有准确重建的细节(为了简单或无意的疏忽):
具有以下字段的用户表:
表名:USERS
USER_IDENTIFIER:GUID(在本例中兼作密码哈希的盐值)
USERNAME_HASH: HASH(用户名 + site_salt)
PASSWORD_HASH:哈希(密码 + USER_IDENTIFIER)
USER_KEY: ENCRYPT(value: <系统生成的随机数>,
键:HASH(USER_IDENTIFIER+用户名+密码))
也可以有一个未加密的公共名称(只要它与用户名不同就不是问题)。
一个组表,由于缺少更好的名称,具有以下字段:
表名:组
GROUP_ID:GUID
OWNER_ID:拥有该组的用户的 USER_IDENTIFIER
GROUP_KEY: ENCRYPT(value: <系统生成的随机数>,
密钥:<拥有用户的未加密 USER_KEY>)
允许组所有者与其他用户共享组密钥的查找表,如下所示:
表名:SHARED_GROUP_KEYS
GROUP_ID:拥有该组的用户正在共享的组的 GUID
USER_ID:使用上述 GROUP_ID 访问组的用户的 GUID
SHARED_KEY:ENCRYPT(值:组的未加密 GROUP_KEY,
密钥:获取用户的未加密 USER_KEY)
然后,数据库中的信息将在组内共享。如果您已被授予访问某个组的权限(通过在该组的 SHARED_GROUP_KEYS 表中拥有一个有效条目),您就拥有查看与该组关联的内容的密钥。否则你不会。
为了进行身份验证,用户只提供用户名和密码。
所以回到最初的问题,它只关注 USER 表的 USERNAME_HASH 字段,为了防止用户名在发生妥协时溢出,对用户名进行散列而不是将其存储为明文是否有意义?换句话说,正如我在下面的评论中提到的,改变将用户名视为公共信息的范式是否有任何优点,而是将其视为另一个秘密(仅用于身份验证)?它是否有助于防止我的站点成为用户凭据的来源,从而允许未经授权访问该用户在另一个站点上的信息?