1

我正在用 MySQL 构建一个 Django 网站。我已经决定使用 Django 内置的 pbkdf2-sha256 和随机生成的盐哈希来存储用户的密码。

但是,该网站还需要为许多其他网站(不使用 oauth)存储第三方登录凭据。所以我一直在研究 AES-256 加密,当然问题在于安全存储加密密钥的位置。

现在这是我的解决方案:让每个加密密钥 = 用户实际密码的哈希值和随机生成的盐值(不同于已用于密码存储哈希值的盐值)。盐将存储在表中,实际密码和它的哈希显然不是。因此,加密密钥将在登录时生成并临时存储,但在注销时过期。此外,如果不破解原始 pbkdf2-sha256 哈希,破坏服务器的人无法生成加密密钥,即使那样,它也只能用于那个用户,而不是通用密钥。

不利的一面是,如果他们更改/重置密码,他们将不得不为每个站点重新输入他们的凭据。但这并不是什么大不了的事,而且似乎比将密钥存储在服务器上的某个地方甚至不同的服务器上更安全。

但我在 24 小时前才知道哈希是什么,所以我知道什么。我是否忽略了某些东西,或者这是否合理安全?或者,还有更好的方法?

4

1 回答 1

3

您提到的算法PBKDF2实际上是为此明确目的而设计的。

因此,工作流程将是生成随机盐。然后将其存储在用户的数据库中。

使用具有高迭代次数和盐的 PBKDF2,生成 640 位密钥材料(80 字节)。

前 128 位成为密码的 IV

接下来的 256 位成为密码密钥(用于 AES-256 的密钥)

最后的 256 位成为 MAC 密钥(用于验证加密的密钥)。

key = PBKDF2-SHA256(password, salt, 50000, 80)
iv = key[0:128]
cipherKey = key[128:384]
macKey = key[384:640]

然后,使用这些密钥(伪代码)加密数据:

ciphertext = AES-256-CBC(data, cipherKey, iv)
authtext = SHA256-HMAC(ciphertext, macKey)
result = '{}{}'.format(authtext, ciphertext)

现在,在解密时,只需倒退...

key = PBKDF2-SHA256(password, salt, 50000, 80)
iv = key[0:128]
cipherKey = key[128:384]
macKey = key[384:640]

authtext = result[0:32]
ciphertext = result[32:]

if !timingSafeComparison(authtext, SHA256-HMAC(ciphertext, macKey)):
    return false

return AES-256-CBC-DECRYPT(ciphertext, cipherKey, iv)

是的,如果您的用户忘记了密码,所有加密数据都将消失。但这就是你想要的,对吧?

于 2013-06-21T18:18:52.193 回答