简体   繁体   English

password_verify和doveadm如何在没有盐的情况下验证密码

[英]How can password_verify and doveadm pw -t verify a password without salt

im currently trying to understand hashes and salts. 我目前正试图了解哈希和盐。 As i understand it, it should not be possible to verify a password, if i only have the password and the generated hash(that was generated with a random salt ofc). 据我了解,如果我只有密码和生成的哈希(用随机盐的生成)生成,则不应该验证密码。 So how can the password_verify function in PHP verify my password , if i dont give it the salt? 那么,如果我不给它盐,那么PHP中password_verify函数如何验证我的密码呢? Is there a hidden variable in the background, that stores it for the php hashing functions? 在后台是否有一个隐藏变量,它存储它用于php散列函数?

And if that is the case, how can 如果是这样,怎么可能

doveadm pw -t '{SHA512-CRYPT}$6$myhash...' -p "qwertz"

verify it too, even if i run it on a complety different computer? 验证它,即使我在完全不同的计算机上运行它? Thats a tool, that comes with Dovecot(a MDA). 这是Dovecot(MDA)附带的工具。

Here is my PHP code, that creates a random salt with 64 chars, combines it with a password, creates a hash and verifies the hash via password_verify() . 这是我的PHP代码,它创建一个包含64个字符的随机盐,将它与密码组合,创建一个哈希并通过password_verify()验证哈希。

I just started working on the whole hash/salt/pepper thing today, so there could be a huge flaw in my whole train of thought. 我今天刚刚开始研究整个hash/salt/pepper事情,所以在我的整个思路中可能存在一个巨大的缺陷。

<?php
$password = "qwertz";
$salt = createSalt(64);
$hash = crypt($password, "$6$$salt");

if (password_verify($password, $hash)) {
    echo 'Password is valid!';
} else {
    echo 'Invalid password.';
}


function createSalt($length){
    $chars = "IrhsYyLofUKj4caz0FDBCe2W9NRunTgQvp7qOXmS5GM3EJV6i8tAHdkPbxwl1Z";
    $salt="";
    for($i=0; $i < $length; $i++){
        $newchar = substr($chars, rand(0,strlen($chars)-1),1);
        $salt .= $newchar;
    }
    return $salt;
}
?>

The hash contains several pieces of information. 哈希包含几条信息。 This article explains the format used by Unix but I believe PHP password functions use a similar format (if not the same): 本文解释了Unix使用的格式,但我相信PHP密码函数使用类似的格式(如果不相同):

The hash field itself is comprised of three different fields. 哈希字段本身由三个不同的字段组成。 They are separated by '$' and represent: 它们以'$'分隔,代表:

  • Some characters which represents the cryptographic hashing mechanism used to generate the actual hash 一些字符表示用于生成实际哈希的加密哈希机制
  • A randomly generated salt to safeguard against rainbow table attacks 随机生成的盐,以防止彩虹表攻击
  • The hash which results from joining the users password with the stored salt and running it through the hashing mechanism specified in the first field 通过将用户密码与存储的salt连接并通过第一个字段中指定的散列机制运行它而产生的散列

It can also include the exact per-algorithm options used to generate the hash, such us the algorithmic cost: 它还可以包括用于生成哈希的精确的每算法选项,例如算法成本:

var_dump(password_hash('foo', PASSWORD_BCRYPT, [
    'cost' => 8,
]));
 string(60) "$2y$08$7Z5bTz7xXnom8QsrbZ7uQetMLxOZ7WjuDkUYRIh73Ffa17GV1Tb7q" 

Here $2y$08$ means that Bcrypt with cost 8 was used. 这里$2y$08$意味着使用了成本为8的Bcrypt。

If we use the newer Argon2 available in PHP/7.2 there're even more params: 如果我们使用PHP / 7.2中提供的更新的Argon2,那么还有更多的参数:

$argon2i$v=19$m=1024,t=2,p=2$YzJBSzV4TUhkMzc3d3laeg$zqU/1IN0/AogfP4cmSJI1vc8lpXRW9/S0sYY2i2jHT0

Some backgrounds to the answer from @Álvaro González : @ÁlvaroGonzález答案的一些背景:

PHP manual suggests using "password_hash" instead of "crypt" function through "password_hash" is a "crypt()" wrapper ( Because, it uses a strong hash, generates a strong salt, and applies proper rounds automatically. ) PHP手册建议使用“password_hash”而不是“crypt”函数,通过“password_hash”是“crypt()”包装器(因为,它使用强哈希,生成强盐,并自动应用适当的轮次。)

"password_hash()" returns the algorithm, cost, and salt as part of the returned hash. “password_hash()”返回算法,成本和salt作为返回哈希的一部分。 Therefore, all information that's needed to verify the hash is included in it. 因此,验证哈希所需的所有信息都包含在其中。 This allows the "password_verify" function to verify the hash without needing separate storage for the salt or algorithm information. 这允许“password_verify”函数验证散列,而无需为salt或算法信息单独存储。 : http://php.net/manual/en/function.password-verify.php http//php.net/manual/en/function.password-verify.php

Since, "password_hash" is a wrapper for "crypt", "crypt" also does the same, ie., returns the algorithm, cost, and salt as part of the returned hash. 由于“password_hash”是“crypt”的包装器,“crypt”也会执行相同的操作,即返回算法,成本和salt作为返回哈希的一部分。 and thus "password_verify" can verify the hash. 因此“password_verify”可以验证散列。

Now, please check the answer given by @Álvaro González 现在,请查看@ÁlvaroGonzález给出的答案

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM