在PHP中使用crypt()比较密码

sor*_*ist 17 php encryption bcrypt

我需要了解这个功能的基础知识.对于blowfish算法,php.net文档指出:

Blowfish用盐进行散列如下:"$ 2a $",两位数的成本参数"$",以及字母"./0-9A-Za-z"中的22位64位数字.在salt中使用此范围之外的字符将导致crypt()返回零长度字符串

因此,根据定义,这不应该起作用:

echo crypt('rasmuslerdorf', '$2a$07$usesomadasdsadsadsadasdasdasdsadesillystringforsalt$');
Run Code Online (Sandbox Code Playgroud)

然而,它吐出:

$2a$07$usesomadasdsadsadsadaeMTUHlZEItvtV00u0.kb7qhDlC0Kou9e
Run Code Online (Sandbox Code Playgroud)

看来crypt()已将盐本身切成22的长度.有人可以解释一下吗?

我无法理解这个功能的另一个方面是当他们使用crypt()来比较密码时.http://php.net/manual/en/function.crypt.php(见前#1).这是否意味着如果我使用相同的盐来加密所有密码,我必须首先加密它?即:

$salt = "usesomadasdsadsadsadae";
$salt_crypt = crypt($salt);

if (crypt($user_input, $salt) == $password) {
   // FAIL WONT WORK
}

if (crypt($user_input, $salt_crypt) == $password) {
   // I HAVE TO DO THIS?
}    
Run Code Online (Sandbox Code Playgroud)

谢谢你的时间

ZZ *_*der 21

以下代码示例可能会回答您的问题.

要使用Blowfish生成散列密码,首先需要生成一个salt,它以$ 2a $开头,后跟迭代计数和22个字符的Base64字符串.

$salt = '$2a$07$usesomadasdsadsadsadasdasdasdsadesillystringfors';
$digest = crypt('rasmuslerdorf', $salt);
Run Code Online (Sandbox Code Playgroud)

将整个$ digest存储在数据库中,它包含salt和digest.

比较密码时,只需这样做,

  if (crypt($user_input, $digest) == $digest)
Run Code Online (Sandbox Code Playgroud)

您正在重复使用摘要作为盐.crypt知道算法标识符中的salt有多长.

  • @soren.qvist:不完全,不.即使攻击者知道盐,他仍然必须重新计算每个可能密码的哈希值,并附上该盐; 仅计算一次然后只查找结果中的哈希值是不够的.如果盐是未知的,那就更好了,因为他必须为每个可能的盐尝试所有密码,但即使每个用户的盐与每个密码一起存储,它仍然需要重新计算该用户的盐.另见http://en.wikipedia.org/wiki/Salt_%28cryptography%29. (2认同)
  • @soren.qvist:您绝对应该为每个*记录*使用不同的盐。无论它是随机的还是非随机的——我不确定有多大区别。即使盐是可预测的,您仍然需要为每个盐运行哈希。更改密码时创建新的salt也是一样的;您仍然需要计算该盐的所有内容。它可以防止某人通过预先计算哈希值然后重新使用它来瞄准特定用户,但仅此而已。然而,话虽如此,在每次更改时随机添加盐肯定不会“伤害” - 所以你不妨这样做。 (2认同)