用户密码作为密钥而不是散列它

信息安全 验证 哈希
2021-09-03 16:18:00

我在这里阅读 Hashes and Salts 并考虑了另一种进行用户身份验证的方法。我需要您对此的想法,因为我可能会忽略某些东西。

设想:

对于 Web 应用程序身份验证,一般趋势是对密码附加随机盐进行哈希处理,具有强大的哈希函数。随机盐和生成的哈希存储在数据库中。稍后,当用户想要进行身份验证时,用户输入的密码会再次与存储的 salt 进行散列,并将生成的散列与之前存储的散列进行比较。

现在谈谈我的方法:

  1. 我们在我们的数据库中存储一个主密钥文本(只要它需要),并且我们对每个用户使用唯一的盐。
  2. 我们不是存储密码哈希,而是使用用户密码作为密钥对称加密 (hash(master secret + salt)) 并将这个加密值存储在我们的数据库中。
  3. 当用户想要进行身份验证时,这个先前存储的加密值将使用用户密码作为密钥进行解密,我们将得到一个哈希(master secret + salt)。这个解密的哈希将与新计算的哈希(主密码+盐)进行比较
  4. 如果用户输入错误的密码,解密将失败,我们将得到一个错误的哈希值,无法与哈希值(master secret + salt)进行比较

通过这种方式,我们不会以任何形式(纯文本、哈希、加密)将用户密码存储在数据库中。我想知道这种方法与我们常用的密码散列方法相比如何。

4个回答

确实存储了“散列”密码。准确地说,您在服务器上存储了一些数据:

  • S(“盐”)。
  • “主机密” M(这不可能是真正的机密,因为服务器将其“按原样”存储在其内脏中的某个位置)。
  • E(h(M||S),K):加密MS连接的散列,使用或多或少直接从用户密码导出的密钥K。

给定这些数据元素和潜在的密码P,可以进行一些计算,得出布尔结果:P是否是正确的密码。这很正常:服务器必须能够验证传入的密码,只使​​用服务器“知道”的内容。但是,如果服务器可以做到这一点,那么获得服务器数据副本的攻击者也可以做到。这是不可避免的。存储的数据元素不能直接用于重新计算密码,只能用于验证给定的密码,所以这是单向的。

这称为密码散列存在所谓的“主机密”并且内部使用加密功能只是红鲱鱼;您只是在制作自定义密码散列函数。


可能是在“主秘密”一定的价值,如果你真的可以保持它的“秘密”。服务器必须知道它才能操作,所以它并不是真正隐藏的,但您可以安排它存储在数据库中,使其远离通常的 SQL 注入攻击。但是,它不会对在您的服务器上获得 root shell 的攻击者做任何事情。

在密码散列函数中使用这样的“秘密”称为“peppering”,通常的、密码学家认可的方法是使密码散列函数成为一个以“秘密”为密钥MAC

有关密码散列、其概念、工具和术语的入门知识,请参阅这个长答案

我对您的概念的理解如下:-

Master Secret = "ReallyRandomAndSecureStringToUseAsASecret"

**User Registration**
dbPwd = Encrypt((hash(MasterSecret,Unique Salt),Key)
Store dbPwd

**User Login**
Take key as input.
Obtain MasterSecret and Unique Salt from DB.

dbHash = Decrypt(dbPwd,Key)

If, hash(MasterSecret + Unique Salt) == dbHash
    //Valid Login
else
    // Invalid Login

需要考虑的要点: 如果服务器被入侵,Master Secret、Unique Salt 和 dbPwd 将被泄露。

dbHash = 从散列的衍生(MasterSecret,Unique Salt)中得知。dbPwd = 已知来自 db。

现在,攻击者可以离线暴力破解 Decrypt(dbPwd,Key),其中 Key 使用规则、单词表等进行更改。如果遇到用户密钥,解密将给出 dbHash 来确认它。

因此,虽然相当创新,但我不相信您的方法会带来安全优势,除非您希望该机制的模糊性能够阻止攻击者。

tl;博士:

缺点:

任何系统的安全性很大程度上取决于使用它的人的知识和思维方式。- 马蒂·阿哈罗尼

1) 您的系统需要攻击者解决对称解密问题,而不是计算单向哈希。在任何一种情况下,如果用户密码很弱,它就会被破坏。

2) 使用的对称加密算法的强度。

我相信单向哈希在计算上比对称加密更难解决,但是这是对所使用的确切算法的比较。

优点: 您的方法似乎可以确保如果用户密码很强大,那么它将防止哈希冲突。哈希冲突负责(在某些情况下)允许访问帐户,即使真实密码未知。但是请注意,这是以您的 dbPwds 具有可变长度而不是固定长度哈希为代价的。在开发过程中必须考虑到这一点。 参考https ://crypto.stackexchange.com/questions/3952/is-it-possible-to-obtain-aes-128-key-from-a-known-ciphertext-plaintext-pair

假设攻击者可以访问存储在数据库中的机密、盐和加密哈希值,那么您就必须担心对称加密方案的强度。您的加密应该能够抵抗已知纯文本攻击(http://en.wikipedia.org/wiki/Known-plaintext_attack)。目前,可以使用 AES。

如果攻击者知道你正在使用的加密/散列算法,他可以从源代码中获得,他可以像往常一样暴力破解。首先用他正在测试的密钥解密,然后比较哈希值。

请注意,这将改变散列冲突率。

我会简单地在哈希中添加一些胡椒粉——它对你来说更容易预测,而且也很容易被利用。尽量不要适应任何常见的,例如 oclhashcat 支持的那些。