当我使用generate_password_hash()
函数时,我得到一个包含随机盐的加密密码字符串。
>>> from werkzeug.security import generate_password_hash, check_password_hash
>>> generate_password_hash('password')
>>> 'pbkdf2:sha1:1000$3j8Brovx$9acddcd67da9e4c913817231c882a0f757e2d095'
如果我将此字符串存储到数据库,其他人入侵我的数据库并获取此字符串,则使用强力破解可以轻松获取原始密码,因为加密密码包含盐。
check_password_hash('pbkdf2:sha1:1000$9HycZ0Qa$94f08a91fba1c040c5bffb6c7e1ab5a6ad4818de', 'password')
在使用generate_password_hash()
之前,我是否应首先使用自己的盐加密原始密码,还是有更好的解决方案?
感谢。
答案 0 :(得分:2)
使用暴力破解很容易获得原始密码,因为加密密码包含盐。
不,它很容易"蛮力,因为你的迭代次数很少为1000。
在使用
generate_password_hash()
之前,我是否应首先使用自己的盐加密原始密码,还是有更好的解决方案?
不,加密是可逆的,因为丢失的数据库也意味着加密密钥也可能丢失,这意味着额外的加密是无用的。
一个简单的解决方法是将迭代次数增加到一百万或一千万,具体取决于您的服务器上可以承受的费用,因为身份验证程序较慢,您的用户不会逃跑。
generate_password_hash('password', method='pbkdf2:sha256:1000000')
PBKDF2的问题在于它可以很容易地并行化,因为它不需要太多内存。有一些替代品,如scrypt和Argon2,可配置为需要大量内存。内存是目前基于ASIC的专用密码暴力破解机的主要限制。
最终,如果您的用户正在使用"密码1"那么,您所做的任何事情都将导致安全的身份验证系统。作为他们的密码。您应该要求您的用户使用至少包含12个字符的复杂密码,包括大写字母,小写字母和数字(可选择包括特殊字符)。那些也不应该是字典的一部分。
答案 1 :(得分:2)
存储密码哈希时,主要假设是使用强力检索密码太困难了。如果您希望它更安全,请使用更慢的哈希算法和更长的密码。
加密比哈希更糟糕,因为哈希是不可逆的,而暴力是检索密码的唯一方法。通过加密,蛮力只是其中一种选择。
一旦清楚,您可以选择在代码中使用“秘密”盐,或者可以使用哈希保存salt。 使用密码保存盐更安全!为什么?因为每个密码都有不同的盐,所以入侵者必须分别强制使用每个密码。如果您有一个全局salt值,则可以一次性对数据库中的所有密码执行强制操作。