我在纯抽象级别询问(不需要代码)。
一些数据将代表用户存储在网络服务器/数据库中。使用用户密码作为密钥对数据进行加密,确保如果服务器或数据库被攻破,对攻击者来说相对无用。
问题是重置用户密码的标准过程(向他们发送带有令牌的链接)将不起作用,因为在不知道以前的密码的情况下无法解密和重新加密数据。
有没有其他方法可以解决这个问题?
我在纯抽象级别询问(不需要代码)。
一些数据将代表用户存储在网络服务器/数据库中。使用用户密码作为密钥对数据进行加密,确保如果服务器或数据库被攻破,对攻击者来说相对无用。
问题是重置用户密码的标准过程(向他们发送带有令牌的链接)将不起作用,因为在不知道以前的密码的情况下无法解密和重新加密数据。
有没有其他方法可以解决这个问题?
当您说您愿意使用某种自动身份验证来重置密码时,您实际上是在说有两个密码:“普通”密码和“身份验证”密码。您的问题的解决方案是使用随机密钥加密文件,然后使用每个密码加密密钥。
作为一个具体的例子:
为了使它真正完整,让我们假设您的身份验证方案像许多人一样非常宽容。你只会接受“花栗鼠”(或“花栗鼠”,甚至可能是“花栗鼠”)而不是“花栗鼠”。但无论它是什么,你的方案必须是确定性的。您将接受的每个可能的答案都必须解析为相同的哈希值。在这种情况下,我将假设您将安全答案小写,删除文章,如果它是复数,则减少为单数。然后你把问题放在前面。所以你的二级密码类似于“mascot:chipmunk”。
您现在组成一个随机的 16 字节并使用该密钥来加密数据。然后,您使用普通的基于密码的加密技术(例如 PBKDF2)使用上面的每个密码来加密密钥。然后你扔掉钥匙和密码。
当您需要进行重置时,使用提供的密码(“mascot:chipmunk”)解密真正的密钥,并使用新密码(和“mascot:chipmunk”再次)重新加密密钥。
一个可用性问题是密码重置会使所有其他安全答案无效,用户必须重新配置它们。如果这是一个问题,您可以将所有安全答案放入一个包中,并使用与数据相同的技术对其进行加密。(即,安全答案针对所有安全答案进行了加密。)
这种方法当然会创建两个(或更多)可以解锁数据的密码,从而显着减少暴力搜索时间。在扩展事物时,您应该考虑到这一点。也就是说,您的安全裕度通常应该是几个数量级,因此即使是几个密码也应该适用于许多情况。还要记住,安全问题存在于一个很小的关键空间中,尤其是诸如“吉祥物”或“汽车制造”之类的东西,它们可能只有几十个可能的值(除非你去我的高中,那里有一个真正奇怪的吉祥物……)这只是意味着积极调整 PBKDF2 更为重要。
当然,任何类型的密码重置系统的存在都会使有针对性的攻击变得更加容易。但无论您如何实施加密,这都是事实。
但是,如果连安全问题都没有怎么办?如果您仅根据电子邮件地址重置密码怎么办?那么,电子邮件地址就是密码。面对被盗的数据库,这是有问题的,而且很难修复,因为没有真正的秘密(加密需要秘密)。但一切并没有完全丢失。您可以做的一件事是永远不要在数据库中包含实际的电子邮件地址。将电子邮件地址视为密码(因为在这种情况下)。存储哈希。您不能在其上使用随机盐,但您仍然可以对整个数据库使用一些单一的盐。
所以我的电子邮件是 test@example.com。您将其视为密码,用“mygreatservice”对其进行加盐并通过 PBKDF2 运行它。要登录,只需再次将其视为密码即可。
但是,攻击者必须一次猜测一个电子邮件地址。这并不难,但他不能一口气解密整个数据库,而且他永远不会从他猜不到的电子邮件中获取数据。(而且您确实选择了一种非常简单的重置机制。)
为什么需要对密码进行解密?如果他们忘记了,那么您必须根据他们有权访问发送重置令牌的电子邮件帐户这一事实来验证他们。理想情况下,您会在重置页面上包含其他形式的问题/身份证明,例如秘密问题。
此外,您最好不要使用可逆加密存储密码,而是使用强加盐散列,这是一种方法。