PHP - 如何创建安全的 10 位密钥


PHP - How to create a secure 10 digits key

好吧,我需要一种方法来创建与以下模式匹配的 10 位随机唯一键:

LLNNNLLNNN

其中 L 是字母,N 是数字。

我已经找到了一个解决方案,但我正在寻找一些聪明的意见。我的解决方案是(php):

        $alhpabet = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','X','W','Y','Z']; //26 letras         
        $transaction_id = ''; //string
        //Two first letters
        $transaction_id .= $alhpabet[secure_random_number(0,25)];
        $transaction_id .= $alhpabet[secure_random_number(0, 26)];
        //3 first numbers (3 digits)
        $transaction_id .= str_pad(secure_random_number(0, 999),3,'0',STR_PAD_LEFT);
        //last letters
        $transaction_id .= $alhpabet[secure_random_number(0,25)];
        $transaction_id .= $alhpabet[secure_random_number(0, 26)];
        //last numbers
        $transaction_id .= str_pad(secure_random_number(0, 999),3,'0',STR_PAD_LEFT);

我生成secure_random_number的函数是:

function secure_random_number($min, $max){
$range = $max - $min;
if($range == 0)
    return $min; // not so random...
$log = log($range, 2);
$bytes = (int) ($log / 8) + 1; // length in bytes
$bits = (int) $log + 1; // length in bits
$filter = (int) (1 << $bits) - 1; // set all lower bits to 1
do{
    $rnd = hexdec(bin2hex(openssl_random_pseudo_bytes($bytes, $s)));
    $rnd = $rnd & $filter; // discard irrelevant bits
}while($rnd >= $range);
return $min + $rnd;
}

PS:我在这里的某个地方得到了这个,但忘记注意演职员表......

注意:我不担心性能。

作为一般经验法则,当样本数(数据库项)接近键总数的平方根时,可能会发生键冲突。想想生日问题:即使只有23人的房间,50%的时间也会有两个生日相同,因为23>sqrt(365.25)。

您的密钥方案只有 456,976,000,000 个值 (26 ** 4 * 10 ** 6)。其中 Sqrt 是 676,000。这意味着即使数据库中只有五十万个左右的项目,您也可能会出现冲突。你如何选择它们完全无关紧要。

总是算法的傻瓜。这里有一个你可能喜欢的递归广义变体:

function gencode($pattern) {
  if ($key = substr($pattern, 0, 1)) {
      $code = ($key == 'L') ? chr(rand(65, 90)) : rand(0, 9);
      return $code.gencode(substr($pattern, 1));
  } else return null;
}
echo gencode('LLNNNLLNNN');

函数 gencode 将采用任何长度的任何模式,并根据 L 和 N 的模式生成随机代码。