加密和随机生成的盐 [英] bcrypt and randomly generated salts

查看:580
本文介绍了加密和随机生成的盐的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我正在尝试bcrypt.我有一个类(如下所示,该类来自

So I was experimenting with bcrypt. I have a class(shown below, which I got from http://www.firedartstudios.com/articles/read/php-security-how-to-safely-store-your-passwords) in which there are 3 functions. 1st one is to generate a random Salt, the 2nd to generate a hash using the 1st generated Salt and the last one is to verify the supplied password by comparing it with the hashed password.

<?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.接下来,如果我再次输入'password'并使用验证功能,我将得到true表示密码匹配.如果输入错误的密码,我将得到错误的密码.我的问题是这怎么可能?随机生成的盐又如何呢?怎么没有效果?

Now if I generate a hash with 'password' for example, I get a hashed password, which took the randmonly generated Salt. Next if I enter 'password' again and use the verify function ,I get true meaning that the passwords match. If I enter wrong password, I get false. My question is how is this possible? What about the randomly generated Salt? How come that is not having any effect?

推荐答案

仔细查看您要处理的值.产生的随机盐为:

Have a good look at the values you're dealing with. The random salt generated will be, say:

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函数的原始输入相同;它包含算法类型和参数,随机盐和哈希结果.

In other words, the first part of the resulting hash is the same as the original input into the crypt function; it contains the algorithm type and parameters, the random salt and the hash result.

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

确认密码后,再次需要原始盐.只有使用相同的盐,才能将相同的密码散列到相同的散列.而且它仍然存在于哈希中,其格式可以传递给crypt,以重复与生成哈希时相同的操作.这就是为什么您需要同时将密码和哈希值输入到验证功能中的原因:

When you confirm a password, you need the same, original salt again. Only with the same salt will the same password hash to the same hash. And it's still there in the hash, in a format that can be passed to crypt as is to repeat the same operation as when the hash was generated. That's why you need to feed both the password and hash into the validation function:

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

crypt会使用第一个定义的字符数,直到并包括abcdefg...,然后将其余的字符丢弃(这就是为什么salt必须是固定数目的字符的原因).因此,它等于以前的操作:

crypt takes the first defined number of characters, up to and including abcdefg... and throws the rest away (that's why the salt needs to be a fixed number of characters). Therefore it equals the same operation as before:

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

并且将生成相同的哈希值,且仅当 $passwordToCheck相同时.

And will generate the same hash, if and only if $passwordToCheck is the same.

这篇关于加密和随机生成的盐的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆