【问题标题】:How does PHP's password_hash generate the salt?PHP 的 password_hash 是如何生成盐的?
【发布时间】:2013-02-03 13:30:57
【问题描述】:

您好,您可能知道 PHP 最近在最新版本中引入了 password_hash 内置。文档说:

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

问题是用什么方法加盐?

我很感兴趣,因为我想知道盐是否是随机创建的,这样当我存储我的散列密码时,它们始终是唯一的

【问题讨论】:

    标签: php password-hash


    【解决方案1】:

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

    要了解如何操作,请查看the C source code

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

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

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

    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() 来填充它。请注意,在实践中这永远不会发生,这只是一个后备:

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

    现在,如果 C 不是你的一杯茶,那么在my compat library 中的 PHP 中实现了相同的逻辑和算法:

    $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 如果安装了任何一个...

    【讨论】:

    • 如果盐是随机的,以后怎么破译。散列(数据+随机盐1)!=散列(数据+随机盐2)??它是如何工作的?请。理解起来让我头疼。
    猜你喜欢
    • 2015-04-17
    • 1970-01-01
    • 2013-10-18
    • 2017-12-28
    • 2014-01-22
    • 1970-01-01
    • 2011-01-31
    • 1970-01-01
    • 2014-05-05
    相关资源
    最近更新 更多