【问题标题】:How to generate a random, long salt for use in hashing?如何生成用于散列的随机长盐?
【发布时间】:2018-01-08 18:31:46
【问题描述】:

在 PHP 中有什么方法可以制作随机的、可变长度的盐以用于散列?假设我想制作一个 16 个字符的长盐 - 我该怎么做?

【问题讨论】:

    标签: php salt-creation


    【解决方案1】:

    编辑:mcrypt 扩展已被弃用。 对于新项目,请查看
    random_bytes ( int $length )
    sodium(从 php 7.2 开始)扩展。


    如果mcrypt extension 可用,您可以简单地使用mcrypt_create_iv(size, source) 创建盐。

    $iv = mcrypt_create_iv(16, MCRYPT_DEV_URANDOM);
    var_dump($iv);
    

    由于“字符串”的每个字节都可以在 0-255 之间的范围内,因此您需要一个二进制安全函数来保存/检索它。

    【讨论】:

    • 到目前为止,该线程中的最佳答案。加密 PRNG 是可行的方法。
    • 这确实应该是公认的答案。为了自己的安全,不要使用薛灿的unique_md5建议。
    • 非常适合像我这样的新手,这很容易理解,使用起来也简单得多,我现在在 XAMPP 上使用它。
    • @VolkerK 你好。 mcrypt_create_iv 似乎是可行的方法,但 PHP 7.1.0 不再支持。有什么选择吗?谢谢
    • 这已被弃用。现在使用docs.php.net/manual/en/function.random-bytes.php
    【解决方案2】:

    取决于您的操作系统,例如:

    $fh=fopen('/dev/urandom','rb');
    $salt=fgets($fh,16);
    fclose($fh);
    

    请阅读 random 和 urandom 的行为。

    虽然其他人已正确指出 md5 和重复散列存在一些问题,但对于密码(即相对较短的字符串)而言,无论散列算法有多复杂,暴力攻击都需要相同的时间。

    C.

    【讨论】:

    • $salt = file_get_contents('/dev/urandom', false, null, 0, 16); :)
    【解决方案3】:

    这是我找到了一个生成随机字符串的函数:

    /* random string */
    function rand_string( $length ) {
        $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";  
        $size = strlen( $chars );
        for( $i = 0; $i < $length; $i++ ) {
            $str .= $chars[ rand( 0, $size - 1 ) ];
        }
        return $str;
    }
    

    【讨论】:

      【解决方案4】:

      一个好的盐有两个先决条件:它必须是长的,它必须是随机的。有很多方法可以做到这一点。例如,您可以使用microtimerand 的组合,但您可能会更加努力以确保您的盐是独一无二的。

      虽然发生冲突的可能性可以忽略不计,但请记住,使用 MD5 或其他容易发生冲突的算法对您的盐进行散列会降低您的盐无缘无故独一无二的可能性。

      编辑:用rand() 替换mt_rand()。正如 Michael 所说,它比 rand 更好。

      【讨论】:

      • @FRKT:我需要为 crypt() 加盐吗?语法是 crypt(password, salt) ,其中 salt 是可选的,但它似乎决定了使用哪种 crypt 变体,我不知道这对安全性有多大影响。 php.net/manual/en/function.crypt.php
      • @hatorade:手册中提到了 salt 参数:“用于加密的可选盐字符串。如果未提供,PHP 将在每次调用此函数时随机生成一个。”
      • randmt_rand() 都不是加密 PRNG。