首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用crypt()和password_hash()函数加密后,密码不匹配

使用crypt()和password_hash()函数加密后,密码不匹配
EN

Stack Overflow用户
提问于 2013-10-29 23:38:06
回答 2查看 17.6K关注 0票数 13

我修改了我以前的帖子。我尝试了crypt()函数,现在尝试使用password_hash()和password_verify()来验证来自数据库的加密密码,但是在每次调用时,password_hash()函数都会返回一个不同的加密字符串,而password_verify()无法匹配它。

这就是我所做的。

代码语言:javascript
复制
 //please ignore the syntax error if any

$data = '11';
$dbpass = password_hash($data, PASSWORD_BCRYPT);
echo $dbpass;  // displays the random strings on each page refresh.

一旦密码被保存到数据库中,在登录过程中不匹配。下面是我的实际函数。

代码语言:javascript
复制
   private function process_data($password){
    $password = __STR.$password.__STR;
    return  password_hash($password, PASSWORD_BCRYPT);

  }
  private function processed($login_password, $dbpassword){
    $login_password = __STR.$login_password.__STR;
    return password_verify($login_password, $dbpassword);
  }

在每次调用为password创建散列字符串的函数时,该函数下次都会返回不同的字符串。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-10-31 22:17:49

好的,让我们一个接一个地看一遍。

首先,它是散列,而不是加密。加密是双向的,散列是单向的。我们想要散列。我们从来不想加密。是的,术语很重要。请使用正确的术语。

接下来,每次对password_hash的调用都被假定为,以返回不同的散列。这是因为它产生了一种很强的随机盐。这就是它是如何设计的,以及你应该如何使用它。

此外,不会像“”那样在密码前后添加__STR。您什么也不做,只是潜在地削弱了用户密码(这是不好的)。如果你想了解更多关于为什么这不是个好主意的信息,请访问Read This Answer

继续,我强烈建议您不要直接使用crypt。实际上,很容易搞砸并生成极弱的散列。这就是设计password_*应用程序接口的原因。crypt是一个低级库,您希望在代码中使用高级库。有关搞砸bcrypt的更多信息,请查看我的博客:Seven Ways To Screw Up Bcrypt

Password API被设计成一个简单的一站式商店。如果它对你不起作用,请检查以下内容:

  1. 你用的是>= 5.5.0吗?或者,您正在使用带有password_compat

的PHP >= 5.3.7

代码语言:javascript
复制
1. Is your database column wide enough?

它需要至少为 60个字符的长度。

2.是否检查函数的结果是字符串,而不是bool(false)

如果存在内部错误,它将从password_hash返回一个非字符串。

3.你收到什么错误了吗?

您是否将error_reporting设置为最大值(我建议使用-1来捕获所有内容),并检查代码是否没有抛出任何错误?

4.确定使用正确吗?

函数saveUser( $username,$password) { $hash = password_hash($password,PASSWORD_BCRYPT);//将$username和$hash保存到数据库}函数登录($username,$password) { //从数据库获取$hash返回password_verify($password,$hash);}

请注意,每个函数应该只调用一次。

  1. 你在password_compat中使用< 5.3.7吗?如果是这样,这就是你的问题。您正在不支持的PHP版本上使用兼容性库。您可能会让它正常工作(某些RedHat发行版已向后移植了必要的修复),但您使用的是不受支持的版本。请升级到合理的版本。

如果所有其他方法都失败了,请尝试运行此代码并报告输出:

代码语言:javascript
复制
$hash = '$2y$04$usesomesillystringfore7hnbRJHxXVLeakoG8K30oukPsA.ztMG';
$test = crypt("password", $hash);
$pass = $test == $hash;

echo "Test for functionality of compat library: " . ($pass ? "Pass" : "Fail");
echo "\n";

如果返回Fail,则说明您正在运行不受支持的PHP版本,应进行升级。如果它返回pass,那么错误就在您的逻辑中的某个地方(库运行正常)。

票数 45
EN

Stack Overflow用户

发布于 2013-10-30 20:16:07

存储密码的最好方法是使用PHP的函数password_hash()。它会自动为每个密码生成加密安全的salt,并将其包含在生成的60个字符的字符串中。你根本不用担心盐的问题!

代码语言:javascript
复制
// Hash a new password for storing in the database.
// The function automatically generates a cryptographically safe salt.
$hashToStoreInDb = password_hash($password, PASSWORD_BCRYPT);

// Check if the hash of the entered login password, matches the stored hash.
// The salt and the cost factor will be extracted from $existingHashFromDb.
$isPasswordCorrect = password_verify($password, $existingHashFromDb);

你自己的方案非常弱,首先你使用MD5生成密码散列太快,然后你使用静态盐,这违背了盐的目的。也许你想看看我关于safely storing passwords的教程。

编辑以回答更新的问题:

没有必要将__STR添加到密码中(如果您想添加胡椒,还有更好的方法),但您的示例函数实际上应该可以工作。由于随机盐的存在,password_hash()的返回值每次都会不同。这是正确的,函数password_verify()能够提取此盐进行验证。在您的例子中,数据库字段可能是问题所在。确保它可以容纳60个字符的字符串。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19662767

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档