从用户密码安全生成加密密钥?

时间:2012-10-17 13:27:46

标签: django security encryption hash cryptography

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

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

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

缺点是,如果他们更改/重置密码,他们将不得不重新输入每个站点的凭据。但这并不是一件大事,而且似乎比将密钥存储在服务器甚至是其他服务器上更安全。

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

1 个答案:

答案 0 :(得分: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)

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