私はphpでランダムなパスワードを生成しようとしています。
しかし、すべての 'a'を取得していて、戻り値の型はarray型であり、それを文字列にしたいです。コードを修正する方法について何かアイデアはありますか?
ありがとう。
function randomPassword() {
$alphabet = "abcdefghijklmnopqrstuwxyzABCDEFGHIJKLMNOPQRSTUWXYZ0123456789";
for ($i = 0; $i < 8; $i++) {
$n = Rand(0, count($alphabet)-1);
$pass[$i] = $alphabet[$n];
}
return $pass;
}
セキュリティ警告:
Rand()
は暗号学的に安全な疑似乱数ジェネレータではありません。 PHPで暗号学的に安全な疑似乱数列を生成する を探してください。
これを試してください(文字列のstrlen
は常に1
であるため、count
の代わりにcount
を使用します)。
function randomPassword() {
$alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890';
$pass = array(); //remember to declare $pass as an array
$alphaLength = strlen($alphabet) - 1; //put the length -1 in cache
for ($i = 0; $i < 8; $i++) {
$n = Rand(0, $alphaLength);
$pass[] = $alphabet[$n];
}
return implode($pass); //turn the array into a string
}
random_int()
と指定されたrandom_str()
を使用してください。random_int()
がない場合は、 random_compat を使用してください。パスワードを生成しているので、生成したパスワードが予測不可能であることを確認する必要があります。このプロパティが実装に存在することを確認する唯一の方法です。 暗号的に安全な疑似乱数ジェネレータ (CSPRNG)を使用することです。
CSPRNGの要件は、ランダム文字列の一般的なケースでは緩和できますが、セキュリティが関係している場合はそうではありません。
PHPでのパスワード生成に対する簡単で安全、そして正しい答えは RandomLib を使うことです。このライブラリは私だけでなく業界のセキュリティ専門家によっても監査されています。
あなた自身の解決策を発明することを好む開発者のために、PHP 7.0.0はこの目的のために random_int()
を提供するでしょう。まだPHP 5.xを使用している場合は、 PHP 5 random_int()
用のpolyfill を作成したので、PHP 7がリリースされる前に新しいAPIを使用できます。私たちのrandom_int()
polyfillを使うのはあなた自身の実装を書くよりもおそらく安全です。
安全な乱数整数ジェネレータを用意しておくと、安全な乱数文字列を生成するのはpieよりも簡単です。
<?php
/**
* Generate a random string, using a cryptographically secure
* pseudorandom number generator (random_int)
*
* For PHP 7, random_int is a PHP core function
* For PHP 5.x, depends on https://github.com/paragonie/random_compat
*
* @param int $length How many characters do we want?
* @param string $keyspace A string of all possible characters
* to select from
* @return string
*/
function random_str(
$length,
$keyspace = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
) {
$str = '';
$max = mb_strlen($keyspace, '8bit') - 1;
if ($max < 1) {
throw new Exception('$keyspace must be at least two characters long');
}
for ($i = 0; $i < $length; ++$i) {
$str .= $keyspace[random_int(0, $max)];
}
return $str;
}
私はあなたが特定の方法であなたのパスワードを生成しようとしていることを知っています、しかしあなたはこの方法も見たいと思うかもしれません...
$bytes = openssl_random_pseudo_bytes(2);
$pwd = bin2hex($bytes);
これはphp.netサイトから取得したもので、openssl_random_pseudo_bytes関数に入力した数の2倍の長さの文字列を作成します。そのため、上記は4文字のパスワードを作成します。
要するに...
$pwd = bin2hex(openssl_random_pseudo_bytes(4));
8文字のパスワードを作成します。
ただし、パスワードに含まれるのは数字0〜9と小文字の英字a〜fのみです。
2行の小さなコード
デモ: http://codepad.org/5rHMHwnH
function Rand_string( $length ) {
$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
return substr(str_shuffle($chars),0,$length);
}
echo Rand_string(8);
rand_stringを使用すると、作成する文字数を定義できます。
一行で:
substr(str_shuffle('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') , 0 , 10 )
PHP 7を使用している場合は、 random_int()
関数を使用できます。
function generate_password($length = 20){
$chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.
'0123456789`-=~!@#$%^&*()_+,./<>?;:[]{}\|';
$str = '';
$max = strlen($chars) - 1;
for ($i=0; $i < $length; $i++)
$str .= $chars[random_int(0, $max)];
return $str;
}
以下の古い答え:
function generate_password($length = 20){
$chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.
'0123456789`-=~!@#$%^&*()_+,./<>?;:[]{}\|';
$str = '';
$max = strlen($chars) - 1;
for ($i=0; $i < $length; $i++)
$str .= $chars[mt_Rand(0, $max)];
return $str;
}
あなたの最善の策はircmaxellによるRandomLibライブラリです。
使用例
$factory = new RandomLib\Factory;
$generator = $factory->getGenerator(new SecurityLib\Strength(SecurityLib\Strength::MEDIUM));
$passwordLength = 8; // Or more
$randomPassword = $generator->generateString($passwordLength);
これはshuffle()
やRand()
のような通常の乱数関数よりも強い乱数の文字列を生成します(これはパスワード、ソルト、キーのような機密情報に一般的に欲しいものです)。
既存の回答の中には近いものもありますが、次のいずれかがあるため、回答を投稿します。
生成されたパスワードのセキュリティ、少なくとも私見はあなたがそこに着く方法を超越するので、この答えはcount/strlen
問題を回避するでしょう。私はPHP> 5.3.0も想定するつもりです。
問題を構成要素に分解しましょう。
最初の部分として、PHP> 5.3.0が関数 openssl_random_pseudo_bytes
を提供します。ほとんどのシステムは暗号学的に強力なアルゴリズムを使用していますが、ラッパーを使用するので確認する必要があります。
/**
* @param int $length
*/
function strong_random_bytes($length)
{
$strong = false; // Flag for whether a strong algorithm was used
$bytes = openssl_random_pseudo_bytes($length, $strong);
if ( ! $strong)
{
// System did not use a cryptographically strong algorithm
throw new Exception('Strong algorithm not available for PRNG.');
}
return $bytes;
}
2番目の部分では、 base64_encode
を使用します。これは、バイト文字列を受け取り、元の質問で指定されたものに非常に近いアルファベットを持つ一連の文字を生成するためです。 +
、/
、および=
の各文字が最後の文字列に含まれていて、少なくとも$n
文字以上の長さの結果が欲しい場合は、単に次のようにします。
base64_encode(strong_random_bytes(intval(ceil($n * 3 / 4))));
3/4
要素は、base64エンコーディングの結果、バイト文字列の3分の1以上の長さの文字列が得られるという事実によるものです。 $n
が4の倍数で、それ以外の場合は3文字までの長さであるため、結果は正確になります。余分な文字は主にパディング文字=
なので、何らかの理由でパスワードが正確な長さであるという制約がある場合は、必要な長さに切り捨てることができます。これは、特定の$n
に対して、すべてのパスワードが同じ数で終わるため、結果のパスワードにアクセスした攻撃者の推測文字数が最大2つ減少するためです。
追加のクレジットとして、OPの質問のように正確なスペックを満たすことを望むなら、もう少し作業をしなければならないでしょう。ここでは基本的な変換方法をやめて、早急に汚い方法でやります。どちらも62エントリの長いアルファベットのために、結果に使用されるよりも多くの乱雑性を生成する必要があります。
結果の余分な文字については、結果の文字列からそれらを単純に破棄できます。バイト文字列の8バイトから始めると、base64文字の最大約25%がこれらの「望ましくない」文字になるため、これらの文字を単に破棄すると、OPが必要とする長さより短い文字列は得られません。それから正確な長さになるようにそれを切り捨てることができます。
$dirty_pass = base64_encode(strong_random_bytes(8)));
$pass = substr(str_replace(['/', '+', '='], ['', '', ''], $dirty_pass, 0, 8);
より長いパスワードを生成する場合、PRNGに使用されるエントロピープールを排出することが問題になる場合は、パディング文字=
が中間結果のますます小さな割合を占めるようになります。
定数count
のalphabet
ではなくstrlen($alphabet)
が必要です('alphabet'
と同等)。
ただし、Rand
はこの目的に適したランダム関数ではありません。それは暗黙のうちに現在の時刻でシードされているので、その出力は簡単に予測できます。さらに、Rand
は暗号的に安全ではありません。したがって、出力から内部状態を判断するのは比較的簡単です。
代わりに、/dev/urandom
から読んで、暗号的にランダムなデータを取得してください。
base_convert(uniqid('pass', true), 10, 36);
例えば。 e0m6ngefmj4
EDIT
私がコメントで述べたように、その長さはブルートフォース攻撃がそれに対してタイミング攻撃よりよく働くだろうということを意味します、それでそれは「ランダムジェネレータがどれほど安全であるか」について心配することは本当に関係ありません。セキュリティ、特にこのユースケースでは、使いやすさを補完する必要があるため、上記のソリューションは実際には必要な問題に対して十分に有効です。
しかし、安全なランダムな文字列ジェネレータを探しているときにこの回答に出くわした場合(トークンを生成するような人もいると思うので)、このようなコードのジェネレータは次のようになります。
function base64urlEncode($data) {
return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
}
function secureId($length = 32) {
if (function_exists('openssl_random_pseudo_bytes')) {
$bytes = openssl_random_pseudo_bytes($length);
return rtrim(strtr(base64_encode($bytes), '+/', '0a'), '=');
}
else { // fallback to system bytes
error_log("Missing support for openssl_random_pseudo_bytes");
$pr_bits = '';
$fp = @fopen('/dev/urandom', 'rb');
if ($fp !== false) {
$pr_bits .= @fread($fp, $length);
@fclose($fp);
}
if (strlen($pr_bits) < $length) {
error_log('unable to read /dev/urandom');
throw new \Exception('unable to read /dev/urandom');
}
return base64urlEncode($pr_bits);
}
}
これは基本的にずっと単純なsubstr(md5(uniqid()), 0, 8);
と同じです。
もう一つ(Linuxのみ)
function randompassword()
{
$fp = fopen ("/dev/urandom", 'r');
if (!$fp) { die ("Can't access /dev/urandom to get random data. Aborting."); }
$random = fread ($fp, 1024); # 1024 bytes should be enough
fclose ($fp);
return trim (base64_encode ( md5 ($random, true)), "=");
}
少し賢くなること:
function strand($length){
if($length > 0)
return chr(Rand(33, 126)) . strand($length - 1);
}
それをチェックしなさい ここ 。
この単純なコードを使用して、中程度の長さのパスワードを12文字以内で生成します。
$password_string = '!@#$%*&abcdefghijklmnpqrstuwxyzABCDEFGHJKLMNPQRSTUWXYZ23456789';
$password = substr(str_shuffle($password_string), 0, 12);
大文字、小文字、数字、特殊文字を使って試してください。
function generatePassword($_len) {
$_alphaSmall = 'abcdefghijklmnopqrstuvwxyz'; // small letters
$_alphaCaps = strtoupper($_alphaSmall); // CAPITAL LETTERS
$_numerics = '1234567890'; // numerics
$_specialChars = '`~!@#$%^&*()-_=+]}[{;:,<.>/?\'"\|'; // Special Characters
$_container = $_alphaSmall.$_alphaCaps.$_numerics.$_specialChars; // Contains all characters
$password = ''; // will contain the desired pass
for($i = 0; $i < $_len; $i++) { // Loop till the length mentioned
$_Rand = Rand(0, strlen($_container) - 1); // Get Randomized Length
$password .= substr($_container, $_Rand, 1); // returns part of the string [ high tensile strength ;) ]
}
return $password; // Returns the generated Pass
}
10桁のパスが必要だとしましょう。
echo generatePassword(10);
出力例:
、IZCQ_IV\7
@wlqsfhT(d
1!8 + 1\4 @ uD
コメントのように呼んでください。
<?php
/**
* @usage :
* include_once($path . '/Password.php');
* $Password = new Password;
* $pwd = $Password->createPassword(10);
* return $pwd;
*
*/
class Password {
public function createPassword($length = 15) {
$response = [];
$response['pwd'] = $this->generate($length);
$response['hashPwd'] = $this->hashPwd( $response['pwd'] );
return $response;
}
private function generate($length = 15) {
$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*(){}/?,><";
return substr(str_shuffle($chars),0,$length);
}
private function hashPwd($pwd) {
return hash('sha256', $pwd);
}
}
?>
クイックワンそれがあなたが望むものであれば、シンプルでクリーンで一貫したフォーマット
$pw = chr(mt_Rand(97,122)).mt_Rand(0,9).chr(mt_Rand(97,122)).mt_Rand(10,99).chr(mt_Rand(97,122)).mt_Rand(100,999);
これは、このページの別の回答に基づいています https://stackoverflow.com/a/21498316/525649
この答えは16進数文字0-9,a-f
だけを生成します。 16進数のように見えないものについては、これを試してください:
str_shuffle(
rtrim(
base64_encode(bin2hex(openssl_random_pseudo_bytes(5))),
'='
).
strtoupper(bin2hex(openssl_random_pseudo_bytes(7))).
bin2hex(openssl_random_pseudo_bytes(13))
)
base64_encode
は、広範囲の英数字を返します。rtrim
は最後に=
を削除することがあります例:
32eFVfGDg891Be5e7293e54z1D23110M3ZU3FMjb30Z9a740Ej0jz4
b280R72b48eOm77a25YCj093DE5d9549Gc73Jg8TdD9Z0Nj4b98760
051b33654C0Eg201cfW0e6NA4b9614ze8D2FN49E12Y0zY557aUCb8
y67Q86ffd83G0z00M0Z152f7O2ADcY313Gd7a774fc5FF069zdb5b7
これは、ユーザー用のインターフェースを作成するための設定はあまりできませんが、いくつかの目的のためには大丈夫です。特殊文字の欠如を考慮して文字数を増やしてください。
より包括的で安全なパスワードスクリプトを作成しました。これは、2つの大文字、2つの小文字、2つの数字、および2つの特殊文字の組み合わせを作成します。合計8文字です。
$char = [range('A','Z'),range('a','z'),range(0,9),['*','%','$','#','@','!','+','?','.']];
$pw = '';
for($a = 0; $a < count($char); $a++)
{
$randomkeys = array_Rand($char[$a], 2);
$pw .= $char[$a][$randomkeys[0]].$char[$a][$randomkeys[1]];
}
$userPassword = str_shuffle($pw);
//define a function. It is only 3 lines!
function generateRandomPassword($length = 5){
$chars = "123456789bcdfghjkmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ";
return substr(str_shuffle($chars),0,$length);
}
//usage
echo generateRandomPassword(5); //random password legth: 5
echo generateRandomPassword(6); //random password legth: 6
echo generateRandomPassword(7); //random password legth: 7
少なくとも1つの小文字、1つの大文字、1つの数字、および1つの特殊文字を含む長さ8の強力なパスワードを生成します。コードの長さも変更できます。
function checkForCharacterCondition($string) {
return (bool) preg_match('/(?=.*([A-Z]))(?=.*([a-z]))(?=.*([0-9]))(?=.*([~`\!@#\$%\^&\*\(\)_\{\}\[\]]))/', $string);
}
$j = 1;
function generate_pass() {
global $j;
$allowedCharacters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ~`!@#$%^&*()_{}[]';
$pass = '';
$length = 8;
$max = mb_strlen($allowedCharacters, '8bit') - 1;
for ($i = 0; $i < $length; ++$i) {
$pass .= $allowedCharacters[random_int(0, $max)];
}
if (checkForCharacterCondition($pass)){
return '<br><strong>Selected password: </strong>'.$pass;
}else{
echo 'Iteration '.$j.': <strong>'.$pass.'</strong> Rejected<br>';
$j++;
return generate_pass();
}
}
echo generate_pass();