PHP的password_hash如何生成盐? [英] How does PHP's password_hash generate the salt?

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

问题描述

您可能知道,PHP最近引入了 password_hash -in最新版本.该文档说:

Hello as you may know PHP recently introduced password_hash built-in in latest versions. The documentation says:

如果省略,将创建一个随机盐并使用默认成本.

If omitted, a random salt will be created and the default cost will be used.

问题是它使用哪种方法添加盐?

The question is what kind of method does it use to add the salt?

我很感兴趣,因为我想知道是否随机创建了盐,以便在存储哈希密码时,它们始终是唯一的.

I'm interested because I'd like to know if the salt is created randomly so that when I store my hashed passwords they are always unique.

推荐答案

盐是随机创建的.它们在统计上应该是唯一的.

The salt is created randomly. They should be statistically unique.

要了解操作方法,请查看 C源代码.

To see how, check out the C source code.

在Windows上,它将尝试使用php_win32_get_random_bytes()生成盐:

On Windows, it will attempt to use php_win32_get_random_bytes() to generate the salt:

BYTE *iv_b = (BYTE *) buffer;
if (php_win32_get_random_bytes(iv_b, raw_length) == SUCCESS) {
    buffer_valid = 1;
}

在Linux上,它将尝试读取/dev/urandom以生成盐:

On Linux, it will attempt to read /dev/urandom to generate the salt:

int fd, n;
size_t read_bytes = 0;
fd = open("/dev/urandom", O_RDONLY);
if (fd >= 0) {
    while (read_bytes < raw_length) {
        n = read(fd, buffer + read_bytes, raw_length - read_bytes);
        if (n < 0) {
            break;
        }
        read_bytes += (size_t) n;
    }
    close(fd);
}
if (read_bytes >= raw_length) {
    buffer_valid = 1;
}

然后,在这两个之后,如果缓冲区无效(不完整,则可能是部分缓冲区),它将使用rand()进行填充.请注意,实际上这永远都不会发生,这只是一个备用:

Then, after those two, if the buffer is not valid (not full, it could be partial), it uses rand() to fill it out. Note that in practice this should never happen, it's just a fallback:

if (!buffer_valid) {
    for (i = 0; i < raw_length; i++) {
        buffer[i] ^= (char) (255.0 * php_rand(TSRMLS_C) / RAND_MAX);
    }
}

现在,如果C不是您的最佳选择,那么我的compat库中的PHP会实现相同的逻辑和算法. :

Now, if C isn't your cup of tea, the same logic and algorithms are implemented in PHP in my compat library:

$buffer = '';
$raw_length = (int) ($required_salt_len * 3 / 4 + 1);
$buffer_valid = false;
if (function_exists('mcrypt_create_iv')) {
    $buffer = mcrypt_create_iv($raw_length, MCRYPT_DEV_URANDOM);
    if ($buffer) {
        $buffer_valid = true;
    }
}
if (!$buffer_valid && function_exists('openssl_random_pseudo_bytes')) {
    $buffer = openssl_random_pseudo_bytes($raw_length);
    if ($buffer) {
        $buffer_valid = true;
    }
}
if (!$buffer_valid && is_readable('/dev/urandom')) {
    $f = fopen('/dev/urandom', 'r');
    $read = strlen($buffer);
    while ($read < $raw_length) {
        $buffer .= fread($f, $raw_length - $read);
        $read = strlen($buffer);
    }
    fclose($f);
    if ($read >= $raw_length) {
        $buffer_valid = true;
    }
}
if (!$buffer_valid || strlen($buffer) < $raw_length) {
    $bl = strlen($buffer);
    for ($i = 0; $i < $raw_length; $i++) {
        if ($i < $bl) {
            $buffer[$i] = $buffer[$i] ^ chr(mt_rand(0, 255));
        } else {
            $buffer .= chr(mt_rand(0, 255));
        }
    }
}

唯一的区别是,如果已安装PHP版本,则将使用mcryptopenssl ...

The only difference is that the PHP version will use mcrypt or openssl if either is installed...

这篇关于PHP的password_hash如何生成盐?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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