4

好吧,我一直坐在这里,因为几个小时都在这个问题上摸不着头脑,我不知道出了什么问题。我正在尝试通过带有 crypt 的随机盐来加密密码,但是当我尝试登录时,总是错误的。

让我引导您完成脚本:

$cost = 10;
$salt = strtr(base64_encode(mcrypt_create_iv(16, MCRYPT_DEV_URANDOM)), '+', '.');
$salt = sprintf("$2y$%02d$", $cost) . $salt;
$hash = crypt($password, $salt);

echo $hash;
echo crypt($password, $hash);

输出以下密码为“asdfgh”:

$2y$10$865uru.sXJheD9TQKLDnZuTZfpAXv83UDuaSFfb.G2qIxBzEb1pOi
$2y$10$865uru.sXJheD9TQKLDnZuTZfpAXv83UDuaSFfb.G2qIxBzEb1pOi

数据库中的哈希如下所示:

$2y$10$865uru.sXJheD9TQKLDnZuTZfpAXv83UDuaSFfb.G2qIxBzEb1pOi

对于登录脚本,我们有以下代码用于测试目的:

echo $data->hash . '<br>';
echo crypt('asdfgh', $data->hash) . '<br>';
echo crypt('asdfgh', '$2y$10$865uru.sXJheD9TQKLDnZuTZfpAXv83UDuaSFfb.G2qIxBzEb1pOi');

并输出以下内容:

$2y$10$865uru.sXJheD9TQKLDnZuTZfpAXv83UDuaSFfb.G2qIxBzEb1pOi
$2y$10$865uru.sXJheD9TQKLDnZuRRPJQwjWh2PGgtntpcsnRaGzvv5Sfte
$2y$10$865uru.sXJheD9TQKLDnZuRRPJQwjWh2PGgtntpcsnRaGzvv5Sfte

虽然数据库字符串仍然是正确的,即使通过手动将正确的字符串传递给函数,生成的哈希也是不同的。我没有解决方案...

如果有人可以帮助我,我将非常感激。

Windows 上的 PHP 版本 5.4.16

更新:这是带有盐的更新片段:

$cost = 10;
$salt = strtr(base64_encode(mcrypt_create_iv(16, MCRYPT_DEV_URANDOM)), '+', '.');
$salt = sprintf("$2y$%02d$", $cost) . $salt;
$hash = crypt($password, $salt);

$data = array(
    'id' => '',
    'username' => $username,
    'hash' => $hash,
    'email' => $email,
    'salt' => $salt,
);

$this->mdl_registration->_insert($data);
$this->load->view('registration_submit');

对于登录脚本:

function check_login($password) {
    $username = $this->input->post('username');
    $result = $this->get_where_custom('username', $username);
    foreach($result->result() as $data) {
        echo $data->hash . '<br>';
        echo crypt('asdfgh', $data->salt) . '<br>';
        $test = crypt($password, $data->salt);
        if($test == $data->hash) {
            return TRUE;
        }
        else {
            $this->form_validation->set_message('check_login', 'Invalid Username and / or Password');
            return FALSE;
        }
    }
}

用于测试的回声返回以下内容:

$2y$10$ZgbOXM18lArDu/u/Ftsdr.t7VPnLsqLJdC2Dum8pl/flW8LmnnUoS
$2y$10$ZgbOXM18lArDu/u/Ftsdr.s5N5juHB/zq/5SN/7oFAjn9CZKjI9H6
4

2 回答 2

0

Well, my answer doesn't actually solve why this code isn't working. I thought it was due to the $salt not being passed, but apparently crypt() accounts for this so long as the salt is within the provided $hash...

Anyhow, I can suggest an alternative method to accomplish this. Feel free to ignore this and wait for a solution, or adapt this. Up to you.

$password = 'asdfgh';
$salt = dechex(mt_rand(0, 2147483647)) . dechex(mt_rand(0, 2147483647));
$hash = hash('sha256', $password . $salt);
for($round = 0; $round < 60000; $round++)
{
    $hash = hash('sha256', $hash . $salt);
}

This creates the salt slightly differently, uses a different hashing algorithm and also iterates through the hash 60,000 times (relatively short for a user 1-2 seconds).

Store this $salt in the database along with the $hash.

Now, for the login script just include this snippet...

(assuming $password is 'asdfgh')

$newHash = hash('sha256', $password . $salt);
for($round = 0; $round < 60000; $round++)
{
    $newHash = hash('sha256', $newHash . $salt);
}
if($newHash===$data->hash){
  //Match!
}

I tried this with several different data sets and the hashes always matched up, so you could use this.

Or you can wait for a real security expert to come explain why your code didn't work :)

Hope this helped!

于 2013-08-05T18:54:30.170 回答
0

你的盐格式错误。

根据文档

CRYPT_BLOWFISH - Blowfish 用盐散列如下:“$2a$”、“$2x$”或“$2y$”、两位数的成本参数、“$”和字母表中的 22 个字符“./0-9A” -ZZ”。

你的盐有a)无效字符(=作为base64末尾的填充字符)和b)太长(24个字符而不是22个)。

这可能是您的问题的原因。

于 2013-08-20T12:29:24.680 回答