【问题标题】:How secure is encryption for passwords with crypt() in PHP?在 PHP 中使用 crypt() 加密密码的安全性如何?
【发布时间】:2011-08-09 16:26:18
【问题描述】:

我在 PHP 中使用crypt() 加密,如下所示:

<?php
$password = sanitizing_func($_POST['password']);
$var = crypt($password, 'ab');
?>

这有多安全?

在这里找到了更好的解决方案:openwall phpass

感谢Edward Thomson

【问题讨论】:

  • 推荐阅读 - programmers.stackexchange.com/questions/51403/…,进一步指向内容丰富的文章,顺便说一句,你不是在清理用户输入吗?
  • 哦,是的,我这样做了,这是一个例子,我没有按原样放置 POST['password']。我将阅读您的建议链接
  • 你不能相信用户输入!
  • 是的,我知道我有 FatFree 框架来处理所有这些事情
  • @Kumar,他为什么要消毒它?无论如何它都会被加密。

标签: php encryption password-protection crypt


【解决方案1】:

这比你只使用crypt 的设计方式安全性差,密码作为第一个参数,salt 作为第二个参数。

现在您正在使用用户密码作为盐来加密已知的明文。如果您的系统使用 MD5 crypt,那么您只是将盐空间限制为 12 个字符,因此您将用户密码的空间截断为 12 个字符。更糟糕的是,我的系统要求我在盐上使用前缀来指定我的地穴,否则我会得到老派crypt,这意味着盐有两个字符。因此,您已将用户密码的可能长度限制为两个字符。另外,此时即使运行crypt 也没有意义,您不妨只存储他们的两个字符密码,因为盐是密文的前缀,以便后续对crypt 的调用可以传递相同的盐。

此外,您通过在 salt 中使用密码来限制密码的字符空间,因为 salt 的字符空间仅限于 A-Z、a-z、0-9、“.”、“/”。即使您从代码示例中切换参数,每次调用都使用相同的盐数据。这意味着每个密码都有相同的盐。因此,如果您的密码表被暴露,使用字典攻击破解的计算成本会降低。

换句话说,交换密码和盐参数是一个致命的错误。

最后,根本没有理由调用 crypt 两次。如果你想要更好的加密,使用更好的算法,不要更频繁地调用它。例如,如果您使用的是 DES crypt,那么无论您调用多少次,它仍然是一种古老的算法。 (我似乎还记得读过一个算法的多次传递可能会无意中产生弱化的密文。但我面前没有 Schneier。)

您要做的是行业标准:使用强密码,将密码作为第一个参数传递,随机盐数据作为第二个参数传递,并确保您传递的是salt 允许的最大字节数。

【讨论】:

  • 好吧,现在我对随机盐有点迷失了:我该如何取回它?我的意思是如果盐是随机的,我如何在登录中检查它?那里不是更好的常数吗?
  • 没有。您的盐被添加到密文中以获取返回值。对于老式 DES crypt,它将是前两个字符。所以你选择两个随机字符,然后 cryptedPass = crypt(PASSWORD, "ab");其中“ab”是随机盐。 cryptedPass 返回值将以 ab 为前缀,即随机盐。因此,您存储 cryptedPass 结果。然后当用户再次输入他们的密码时,您获取您存储的 cryptedPass,以便您可以获取您最初使用的盐。然后使用他们的输入和原始盐再次运行 crypt(),与 cryptedPass 相比。
  • 谢谢爱德华,只是出现的密码有点短,我已经习惯了 md5 和朋友的很长的字符串(我知道他们使用 raimbow 表有多不安全)......我想相信地穴
  • 我(或其他任何人)很难告诉你什么对你的应用程序来说“足够强大”。一个包含我最近听过的歌曲列表的网站的密码与我的银行对帐单的安全要求相比,与在敌对地区的间谍进行的一些编码通信具有非常不同的安全要求。也就是说,DES 被认为是异常弱的,MD5 也被认为是弱的。您可以使用 SHA-256。您还可以查看 openwall.com/phpass 这是 bcrypt 的实现 - codahale.com/how-to-safely-store-a-password
  • 谢谢,link 做到了,我希望晚上能睡得更好。
最近更新 更多