ランダムな5文字の文字列を生成する


101

重複する可能性が最も少ない、正確に5つのランダムな文字列を作成します。それを行う最善の方法は何でしょうか?ありがとう。


2
あなたはセットに特定の文字を持っています0-9a-zA-Zか?
Yanick Rochon、2011年

このコードゴルフの挑戦は、検索することができますcodegolf.stackexchange.com/questions/119226/...
タイタス

を使用Random::alphanumericString($length)すると、暗号で保護されたランダムデータから供給される0-9a-zA-Zの文字列を取得できます。
CAW

回答:


162
$rand = substr(md5(microtime()),rand(0,26),5);

私の推測は最高でしょう-特殊文字も探しているのでない限り:

$seed = str_split('abcdefghijklmnopqrstuvwxyz'
                 .'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
                 .'0123456789!@#$%^&*()'); // and any other characters
shuffle($seed); // probably optional since array_is randomized; this may be redundant
$rand = '';
foreach (array_rand($seed, 5) as $k) $rand .= $seed[$k];

そして、クロックに基づくもの(インクリメンタルなので衝突が少ない):

function incrementalHash($len = 5){
  $charset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
  $base = strlen($charset);
  $result = '';

  $now = explode(' ', microtime())[1];
  while ($now >= $base){
    $i = $now % $base;
    $result = $charset[$i] . $result;
    $now /= $base;
  }
  return substr($result, -5);
}

注:インクリメンタルは推測しやすいことを意味します。これをソルトまたは確認トークンとして使用している場合は、使用しないでください。「現在」の「WCWyb」は、5秒後には「WCWyg」になります


6
md5()ただし、を使用した場合の問題は、16文字のセット(10桁aからf、つまり文字列文字ごとに4ビット)で構成される文字列が得られることです。これは、いくつかの目的には十分かもしれませんが、暗号化の目的には少なすぎる可能性があります(16シンボルのうち5文字= 16 ^ 5 = 20ビット= 1048576の可能性)。
アーク

3
array_rand($seed, 5)値ではなく配列キーを返すため、コードは機能しません
alumi

1
暗号化ハッシュ関数を使用してランダムな文字を生成することは、少なくとも不適切だと思います。
gronostaj 2013

それは含めることも可能である"'およびバックスラッシュで$charset?これらの文字を含めるには、エスケープシーケンスを使用する必要がありますか?
2015年

1
2番目のスニペットは$len入力パラメーターも使用していません...忘れましたか?
TechNyquist 2015年

76

forループが不足している場合は、次のように使用します。

$s = substr(str_shuffle(str_repeat("0123456789abcdefghijklmnopqrstuvwxyz", 5)), 0, 5);

興味深い解決策...非常に簡潔ですが、これがforを使用するよりも速いのか遅いのか疑問に思います。ただし、ベンチマークに煩わされることはありません:-)
Arc

@matthew str_shuffleは継続的に重複を生成します
SCC

@ user2826057:str_shuffle('ab')を与えるabba、しないがaa。そのstr_repeatための許可を追加します。しかし、そうは言っても、私が与えた解決策は本当に深刻なものではありません...それは機能しますが。
マシュー14

2
RNGが均一に分散していると仮定すると、このようなことが起こる可能性は1/60466176です。
マシュー

1
これは、バウチャーコードを生成する使用例に最適です。私たちのような、文字を混乱削除li10O、などと500のバウチャーのうちには、重複を得ませんでした。
Luke Cousins 14



15

以下は、重複の可能性を最小限に抑える必要があります(GUID mt_rand()から、/dev/*randomまたはGUID からなど、より優れた乱数ソースに置き換えることをお勧めします)。

<?php
    $characters = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
    $result = '';
    for ($i = 0; $i < 5; $i++)
        $result .= $characters[mt_rand(0, 61)];
?>

編集:
セキュリティに懸念がある場合は、実際にはorを使用せ、ランダムデータデバイスが実際にランダムデータを生成するデバイスであり、通常のファイルやなどの予測可能なものではないことを確認してください。有害と考えられる:https : //spideroak.com/blog/20121205114003-exploit-information-leaks-in-random-numbers-from-python-ruby-and-phprand()mt_rand()/dev/zeromt_rand()

編集: PHPでOpenSSLをサポートしている場合は、次を使用できますopenssl_random_pseudo_bytes()

<?php
    $length = 5;
    $randomBytes = openssl_random_pseudo_bytes($length);
    $characters = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
    $charactersLength = strlen($characters);
    $result = '';
    for ($i = 0; $i < $length; $i++)
        $result .= $characters[ord($randomBytes[$i]) % $charactersLength];
?>

$ result。= $ characters [mt_rand(0、strlen($ characters)-1)]を使用したより賢い最初の例
hamboy75

その場合は、長さを事前に決定し、少なくとも変数に格納する必要があります。strlen()ループ内での使用は不要なオーバーヘッドです。特に、その間に文字セットが変更されないことがすでにわかっている場合はなおさらです。
2017

私はそれを疑う、phpは最適化されています、とにかくそれはオプションです:)
hamboy75

7

私はいつも同じ機能を使って、通常はパスワードを生成します。使いやすく便利です。

function randPass($length, $strength=8) {
    $vowels = 'aeuy';
    $consonants = 'bdghjmnpqrstvz';
    if ($strength >= 1) {
        $consonants .= 'BDGHJLMNPQRSTVWXZ';
    }
    if ($strength >= 2) {
        $vowels .= "AEUY";
    }
    if ($strength >= 4) {
        $consonants .= '23456789';
    }
    if ($strength >= 8) {
        $consonants .= '@#$%';
    }

    $password = '';
    $alt = time() % 2;
    for ($i = 0; $i < $length; $i++) {
        if ($alt == 1) {
            $password .= $consonants[(rand() % strlen($consonants))];
            $alt = 0;
        } else {
            $password .= $vowels[(rand() % strlen($vowels))];
            $alt = 1;
        }
    }
    return $password;
}

素敵なコード。ただし、$ altは常に1から0に反転します。代わりに$ altをランダム化する方が良いでしょうか?
ニコアンドラーデ2017年


3
$str = '';
$str_len = 8;
for($i = 0, $i < $str_len; $i++){
    //97 is ascii code for 'a' and 122 is ascii code for z
    $str .= chr(rand(97, 122));
}
return $str

2

AFの文字のみが表示される場合は、次の解決策があります。

str_pad(dechex(mt_rand(0, 0xFFFFF)), 5, '0', STR_PAD_LEFT);

ハッシュ関数を使用することは、ランダムな16進数字のシーケンスを生成するような単純なタスクではやりすぎだと思います。dechex+ mt_randは同じ仕事をしますが、不必要な暗号化作業はしません。str_pad出力文字列の長さが5文字であることを保証します(乱数が0x10000未満の場合)。

重複確率はmt_randの信頼性に依存します。メルセンヌツイスターは、高品質のランダム性で知られているため、タスクによく適合します。


2

PHP arrayの使用を考えるまで、これを行う方法もわかりませんでした。そして、これがランダムな文字列や配列の数値を生成する最も簡単な方法だと確信しています。コード:

function randstr ($len=10, $abc="aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ0123456789") {
    $letters = str_split($abc);
    $str = "";
    for ($i=0; $i<=$len; $i++) {
        $str .= $letters[rand(0, count($letters)-1)];
    };
    return $str;
};

あなたはこのようにこの関数を使うことができます

randstr(20)     // returns a random 20 letter string
                // Or like this
randstr(5, abc) // returns a random 5 letter string using the letters "abc"

1

Brad Christieの回答に似ていますが、sha1文字にアロリズムを使用0-9a-zA-Zし、ランダムな値を前に付けます:

$str = substr(sha1(mt_rand() . microtime()), mt_rand(0,35), 5);

しかし、定義された(許可された)文字を設定した場合:

$validChars = array('0','1','2' /*...*/,'?','-','_','a','b','c' /*...*/);
$validCharsCount = count($validChars);

$str = '';
for ($i=0; $i<5; $i++) {
    $str .= $validChars[rand(0,$validCharsCount - 1)];
}

** 更新 **

以下のようArchimedixが指摘組み合わせの数が指定された文字範囲のために低いので、これは「重複取得の少なくとも可能性」を返すように保証するものではありません。文字数を増やすか、文字列に余分な(特殊)文字を許可する必要があります。あなたの場合、最初の解決策が望ましいと思います。


の使用time()は、の最大100万倍予測可能ですmicrotime()
アーク

また、ブラッドの回答に対する私のコメントにも注意してください。より大きな問題は、生成されたハッシュが16の有効な文字で構成される16進表記であるため、には1024のバリエーションしか残されないことです$str
アーク

@Archimedix、おそらく、OPはセキュリティを要求しませんでした。質問は、5x26の異なる文字の組み合わせで構成される文字列生成アルゴリズムを持ち、重複を避けるように定義されました。これはおそらく、登録プロセス(または請求プロセス)の確認参照番号、または何かのためです
Yanick Rochon '26

重複する可能性最小限抑えるように求めたのは私の理解でした。これは0.1%の確率(1024に1)で、これは10億に1 近くでした。
アーク

ただし、5文字の参照キーを生成してクライアント/顧客に提供する必要がある場合、˫§»⁋⅓より安全であるためにそれらに「」を与えたくない...参照キーを7文字以上に増やす。(ところで:私の以前のコメントの訂正、それは5x36文字です)
Yanick Rochon

1

PHPで正常に動作します(php 5.4.4)

$seed = str_split('abcdefghijklmnopqrstuvwxyz');
$rand = array_rand($seed, 5);
$convert = array_map(function($n){
    global $seed;
    return $seed[$n];
},$rand);

$var = implode('',$convert);
echo $var;

ライブデモ


1

ソース:ランダムな文字を生成するPHP関数

この単純なPHP関数は私にとってうまくいきました:

function cvf_ps_generate_random_code($length=10) {

   $string = '';
   // You can define your own characters here.
   $characters = "23456789ABCDEFHJKLMNPRTVWXYZabcdefghijklmnopqrstuvwxyz";

   for ($p = 0; $p < $length; $p++) {
       $string .= $characters[mt_rand(0, strlen($characters)-1)];
   }

   return $string;

}

使用法:

echo cvf_ps_generate_random_code(5);

1

ここに私のrandom 5 cents...

$random=function($a, $b) {
    return(
        substr(str_shuffle(('\\`)/|@'.
        password_hash(mt_rand(0,999999),
        PASSWORD_DEFAULT).'!*^&~(')),
        $a, $b)
    );
};

echo($random(0,5));

PHPの新しいpassword_hash()(*> = PHP 5.5)関数は、大文字と小文字および数字のまともな長さのセットを生成する役割を果たします。

2つの連結。password_hash$ random関数内の前後の文字列は変更に適しています。

以下のためのParamteres $random()*($、$ b)は、実際にあるsubstr()パラメータ。:)

注:これは関数である必要はありません。通常の変数でもかまいません。

$random=(substr(str_shuffle(('\\`)/|@'.password_hash(mt_rand(0,999999), PASSWORD_DEFAULT).'!*^&~(')), 0, 5));

echo($random);

1
function CaracteresAleatorios( $Tamanno, $Opciones) {
    $Opciones = empty($Opciones) ? array(0, 1, 2) : $Opciones;
    $Tamanno = empty($Tamanno) ? 16 : $Tamanno;
    $Caracteres=array("0123456789","abcdefghijklmnopqrstuvwxyz","ABCDEFGHIJKLMNOPQRSTUVWXYZ");
    $Caracteres= implode("",array_intersect_key($Caracteres, array_flip($Opciones)));
    $CantidadCaracteres=strlen($Caracteres)-1;
    $CaracteresAleatorios='';
    for ($k = 0; $k < $Tamanno; $k++) {
        $CaracteresAleatorios.=$Caracteres[rand(0, $CantidadCaracteres)];
    }
    return $CaracteresAleatorios;
}

プロのヒント-あなたの回答がOPの問題をどのように解決するか、なぜそれがすでに提供されている他の回答と異なる可能性があるのか​​についての説明を含めます。
トム・

0

私は離れてこれを使います:

<?php function fRand($len) {
    $str = '';
    $a = "abcdefghijklmnopqrstuvwxyz0123456789";
    $b = str_split($a);
    for ($i=1; $i <= $len ; $i++) { 
        $str .= $b[rand(0,strlen($a)-1)];
    }
    return $str;
} ?>

これを呼び出すと、文字列の長さが設定されます。

<?php echo fRand([LENGHT]); ?>

文字列で使用できる文字を変更することもできます$a


この機能を無駄に開発するのに時間を無駄にしたことがわかります。私は少しググった!@Andrew
LipESprY
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.