在 PHP 中生成一个真正的随机字符串


Generating a truly random string in PHP

我需要为客户端生成数千(可能数百万)个唯一代码。这些代码可能具有货币价值,因此至关重要的是,它们是真正随机的,并且聪明的黑客无法发现和利用任何模式。

我已经研究了生成代码的各种解决方案(循环生成的 = 可以猜到,风险太大,uniqid() = 好,但我可能需要不同长度的代码)。

现在我正在考虑使用 A-Z 和 0-9 减元音生成代码(以确保不会意外生成粗鲁的单词),尽管将来可能会增加到小写字符等。

到目前为止,我有这个:

编辑:根据@kingero的评论,下面,我提高了解决方案中的随机性赌注,将mt_rand替换为此处的自定义兰德函数:

function generateCode($length = 12) {
    $chars = 'BCDFGHJKLMNPQRSTVWXYZ0123456789';
    $count = mb_strlen($chars);
    for ($i = 0, $result = ''; $i < $length; $i++) {
        $randomIndex = devurandom_rand(0, $count - 1);
        $result .= mb_substr($chars, $randomIndex, 1);
    }
    return $result;
}
// CUSTOM RAND FUNCTION
// equiv to rand, mt_rand
// returns int in *closed* interval [$min,$max]                                                
function devurandom_rand($min = 0, $max = 0x7FFFFFFF) {
    $diff = $max - $min;
    if ($diff < 0 || $diff > 0x7FFFFFFF) {
    throw new RuntimeException("Bad range");
    }
    $bytes = mcrypt_create_iv(4, MCRYPT_DEV_URANDOM);
    if ($bytes === false || strlen($bytes) != 4) {
        throw new RuntimeException("Unable to get 4 bytes");
    }
    $ary = unpack("Nint", $bytes);
    $val = $ary['int'] & 0x7FFFFFFF;   // 32-bit safe                           
    $fp = (float) $val / 2147483647.0; // convert to [0,1]                          
    return round($fp * $diff) + $min;
}

这是非常基本的,所以我显然担心它不够随机。谁能告诉我这是否是确保生成的代码真正随机的体面方法?

(注意:显然,想要成为黑客的人总是能够尝试暴力攻击。此类尝试将在其他地方处理,我只想确保此代码是真正随机的。

我使用以下实现,希望对您有用:

function createRandStr($length, $spChars = false){
        $alpha = 'abcdefghijklmnopqrstwvxyz';
        $alphaUp = strtoupper($alpha);
        $num = '12345678901234567890';
        $sp = '@/+.*-'$#!)[';
        $thread = $alpha.$alphaUp.$num;
        if ($spChars) $thread .= $sp;
        $str = '';
        for ($i = 0; $i < $length; $i++){
            $str .= $thread[mt_rand(0, strlen($thread)-1)];
        }
        return $str;
    } 

查看此现场演示:http://codepad.org/QnvP7fFl