bcrypt和随机产生的盐

所以我正在试验bcrypt。 我有一个类(下面显示,我从http://www.firedartstudios.com/articles/read/php-security-how-to-safely-store-your-passwords ),其中有3个function。 第一个是生成一个随机的Salt,第二个是使用第一个生成的Salt生成一个哈希值,最后一个是通过比较哈希密码来validation提供的密码。

<?php /* Bcrypt Example */ class bcrypt { private $rounds; public function __construct($rounds = 12) { if(CRYPT_BLOWFISH != 1) { throw new Exception("Bcrypt is not supported on this server, please see the following to learn more: http://php.net/crypt"); } $this->rounds = $rounds; } /* Gen Salt */ public function genSalt() { /* openssl_random_pseudo_bytes(16) Fallback */ $seed = ''; for($i = 0; $i < 16; $i++) { $seed .= chr(mt_rand(0, 255)); } /* GenSalt */ $salt = substr(strtr(base64_encode($seed), '+', '.'), 0, 22); /* Return */ return $salt; } /* Gen Hash */ public function genHash($password) { /* Explain '$2y$' . $this->rounds . '$' */ /* 2a selects bcrypt algorithm */ /* $this->rounds is the workload factor */ /* GenHash */ $hash = crypt($password, '$2y$' . $this->rounds . '$' . $this->genSalt()); /* Return */ return $hash; } /* Verify Password */ public function verify($password, $existingHash) { /* Hash new password with old hash */ $hash = crypt($password, $existingHash); /* Do Hashs match? */ if($hash === $existingHash) { return true; } else { return false; } } } /* Next the Usage */ /* Start Instance */ $bcrypt = new bcrypt(12); /* Two create a Hash you do */ echo 'Bcrypt Password: ' . $bcrypt->genHash('password'); /* Two verify a hash you do */ $HashFromDB = $bcrypt->genHash('password'); /* This is an example you would draw the hash from your db */ echo 'Verify Password: ' . $bcrypt->verify('password', $HashFromDB); ?> 

现在,例如,如果我生成一个带有“密码”的散列,我得到一个散列的密码,这个散列密码就是随机生成的Salt。 接下来,如果我再次input“密码”,并使用validationfunction,我得到真正的意思是密码匹配。 如果我input错误的密码,我会得到错误的。 我的问题是如何可能? 那随机产生的盐呢? 怎么没有效果?

仔细看看你正在处理的价值。 生成的随机盐将会是:

 abcdefg... 

喂入crypt看起来像这样:

 crypt($password, '$2y$10$abcdefg...') | | | | | +- the salt | +- the cost parameter +- the algorithm type 

结果如下所示:

 $2y$10$abcdefg...123456789... | | | | | | | +- the password hash | | +- the salt | +- the cost parameter +- the algorithm type 

换句话说,结果散列的第一部分与crypt函数的原始input相同; 它包含algorithmtypes和参数, 随机盐和哈希结果。

 Input: $password + $2y$10$abcdefg... Output: $2y$10$abcdefg...123456789... ^^^^^^^^^^^^^^^^^ first part identical 

当您确认密码时,您需要再次使用相同的原始盐。 只有使用相同的salt,相同的密码才能散列到同一个散列。 它仍然存在于散列中,其格式可以按原样传递给crypt ,以重复与散列生成时相同的操作。 这就是为什么你需要提供密码和散列到validationfunction:

 crypt($passwordToCheck, '$2y$10$abcdefg...123456789...') 

crypt需要第一个定义的字符数,直到并包括abcdefg...并把剩下的扔掉(这就是为什么盐需要是固定数量的字符)。 因此它和以前一样:

 crypt($passwordToCheck, '$2y$10$abcdefg...') 

并且会生成相同的散列, 当且仅当 $passwordToCheck是相同的。