我正在使用Python的crypt包来保存Django网站的MySQL数据库中的加密密码。我不确定这是不是一个错误,但这是我正在使用的代码:
加密/保存密码:
user.password = crypt(request.POST['password'], netid)
user.save()
要在登录时检查密码是否正确:
if crypt(password, email) == user.password:
# Grant acccess to the user's profile, etc.
问题如下。如果我使用变量netid = test@example.com
和request.POST['password'] = 'ABC123abc'
加密密码,则可以正常使用。但是,当我尝试登录时,如果我使用密码'ABC123abc[trailing_chars]'
,其中trailing_chars可以是任何有效字符串,我仍然可以登录。为什么会这样?它本身就是一个很大的安全漏洞。
答案 0 :(得分:6)
首先,你应该不使用电子邮件地址作为crypt的第二个参数(第二个参数)。这不安全。你必须选择一个好的随机盐。
对于传统的crypt,salt是从集合[a–zA–Z0–9./]
中选择的双字符字符串。此版本的crypt仅接受8个输入字符,并在8日之后丢弃输入中的所有后续字符。这就是你在这里看到的。
现代加密实现还支持其他算法,这些算法在加密方面比传统加密更强大,但它们并非在所有平台上都可用。新算法也不会将输入限制为8个字符。
要使用其中一种更好的算法(如果您使用的是支持它们的平台),则需要提供特殊格式的salt。这就是函数识别您想要使用备用算法的方式。
对于glibc支持的额外算法(因此可在GNU / Linux上使用),请参阅crypt manpage的“Glibc Notes”部分。
顺便说一下,在检查密码时,您不需要手动提取盐。加密密码已经以salt开头,因此只需将user.password
(不是email
)作为第二个参数传递给crypt
。无论您使用的是旧算法还是新算法,都可以使用此算法。只有在加密密码时才能选择算法和生成正确格式的盐,而不是在验证密码时。