Создание случайного пароля в php

Я пытаюсь создать случайный пароль в php.

Однако я получаю все «a» и «return type» из массива типов, и я бы хотел, чтобы это была строка. Любые идеи о том, как исправить код?

Благодарю.

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 вместо count , потому что count строки всегда 1 ):

 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 } 

Демо: http://codepad.org/UL8k4aYK

Я знаю, что вы пытаетесь сгенерировать свой пароль определенным образом, но вы можете также взглянуть на этот метод …

 $bytes = openssl_random_pseudo_bytes(2); $pwd = bin2hex($bytes); 

Он взят с сайта php.net и создает строку, которая в два раза больше длины, указанной вами в функции openssl_random_pseudo_bytes. Таким образом, вышесказанное создало бы пароль длиной 4 символа.

Вкратце…

 $pwd = bin2hex(openssl_random_pseudo_bytes(4)); 

Создал бы пароль длиной 8 символов.

Обратите внимание, однако, что пароль содержит только цифры 0-9 и маленькие буквы cap!

TL; DR:

  • Используйте RandomLib .
  • Если вы не можете использовать RandomLib, используйте 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() чтобы вы могли использовать новый API до выхода PHP 7. Использование нашего random_int() вероятно, безопаснее, чем создание собственной реализации.

С надежным генератором случайных целых чисел генерировать безопасную случайную строку проще, чем пирог:

 <?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; } 

Крошечный код с 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 ) 

Если вы используете PHP7, вы можете использовать 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; } 

Ваш лучший выбор – библиотека RandomLib от ircmaxell .

Пример использования:

 $factory = new RandomLib\Factory; $generator = $factory->getGenerator(new SecurityLib\Strength(SecurityLib\Strength::MEDIUM)); $passwordLength = 8; // Or more $randomPassword = $generator->generateString($passwordLength); 

Он создает строки, которые являются более случайными, чем обычные функции случайности, такие как shuffle() и rand() (что вы обычно хотите для чувствительной информации, такой как пароли, соли и ключи).

Вы хотите strlen($alphabet) , а не count постоянного alphabet (что эквивалентно 'alphabet' ).

Однако для этой цели rand не является подходящей случайной функцией. Его выход можно легко предсказать, поскольку он неявно посеян с текущим временем. Кроме того, rand не криптографически безопасен; поэтому относительно легко определить его внутреннее состояние с выхода.

Вместо этого прочитайте из /dev/urandom чтобы получить криптографически случайные данные.

Я собираюсь опубликовать ответ, потому что некоторые из существующих ответов близки, но имеют один из следующих:

  • меньшего пространства символов, чем вы хотели, чтобы облегчить либо грубое форсирование, либо пароль должен быть длиннее для той же энтропии
  • RNG, который не считается криптографически безопасным
  • требование для некоторой сторонней библиотеки, и я подумал, что было бы интересно показать, что это может сделать для этого

Этот ответ count/strlen проблему count/strlen поскольку безопасность сгенерированного пароля, по крайней мере, ИМХО, выходит за рамки того, как вы туда попадаете. Я также собираюсь предположить PHP> 5.3.0.

Давайте разложим проблему на составляющие части, которые:

  1. использовать некоторый безопасный источник случайности для получения случайных данных
  2. использовать эти данные и представлять их как некоторую строку для печати

Для первой части 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; } 

Во второй части мы будем использовать base64_encode так как он принимает байтовую строку и создаст серию символов, которые имеют алфавит, очень близкий к тому, который указан в исходном вопросе. Если бы мы не возражали, чтобы в финальной строке появлялись символы + , / и = и нам нужен результат длиной не менее $n , мы могли бы просто использовать:

 base64_encode(strong_random_bytes(intval(ceil($n * 3 / 4)))); 

Фактор 3/4 обусловлен тем фактом, что кодировка base64 приводит к тому, что строка имеет длину, по крайней мере, на треть больше, чем байтовая строка. Результат будет точным для того, чтобы $n было кратным 4 и до 3 символов в противном случае. Поскольку дополнительные символы в основном являются символом заполнения, если у нас почему-то было ограничение, что пароль будет точной длины, тогда мы можем усечь его до требуемой длины. Это особенно важно, потому что для данного $n все пароли заканчиваются одинаковым числом, так что у злоумышленника, у которого был доступ к паролю результата, было бы до двух меньших символов, чтобы догадаться.


Для дополнительного кредита, если бы мы хотели удовлетворить точную спецификацию, как в вопросе OP, нам пришлось бы сделать немного больше работы. Я собираюсь отказаться от базового подхода к конвертации здесь и пойти с быстрым и грязным. Оба должны генерировать больше случайности, чем будут использоваться в результате в любом случае из-за 62-символьного длинного алфавита.

Для дополнительных символов в результате мы можем просто отбросить их из полученной строки. Если мы начнем с 8 байтов в нашей байтовой строке, то примерно 25% символов base64 будут этими «нежелательными» символами, так что простое отбрасывание этих символов приведет к строке, меньшей, чем требуется OP. Тогда мы можем просто усечь его, чтобы перейти к точной длине:

 $dirty_pass = base64_encode(strong_random_bytes(8))); $pass = substr(str_replace(['/', '+', '='], ['', '', ''], $dirty_pass, 0, 8); 

Если вы создаете более длинные пароли, символ заполнения = формирует меньшую и меньшую долю промежуточного результата, чтобы вы могли реализовать более компактный подход, если проблема сдерживания пула энтропии, используемого для PRNG.

Это в основном то же самое, что и гораздо более простой substr(md5(uniqid()), 0, 8);

base_convert(uniqid('pass', true), 10, 36);

например. e0m6ngefmj4

РЕДАКТИРОВАТЬ

Как я уже упоминал в комментариях, длина означает, что атаки с использованием грубой силы будут работать лучше против нее, а затем синхронизировать атаки, поэтому не стоит беспокоиться о том, «насколько безопасен случайный генератор». Безопасность, особенно для этого варианта использования, должна дополнять удобство использования, поэтому вышеупомянутое решение на самом деле достаточно хорошо для требуемой проблемы.

Однако на всякий случай вы наткнулись на этот ответ, ища надежный генератор случайных строк (как я полагаю, некоторые люди основаны на ответах), для чего-то вроде генерации токенов, вот как выглядит генератор таких кодов:

 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); } } 

Еще один (только для 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 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 Digit Pass

 echo generatePassword(10); 

Пример вывода (ов):

, IZCQ_IV \ 7

@wlqsfhT (д

1! 8 + 1 \ 4 @ UD

Используйте этот простой код для генерации надежного пароля длиной 12

 $password_string = '!@#$%*&abcdefghijklmnpqrstuwxyzABCDEFGHJKLMNPQRSTUWXYZ23456789'; $password = substr(str_shuffle($password_string), 0, 12); 

Быстрый. Простой, чистый и согласованный формат, если это то, что вы хотите

 $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

Этот ответ генерирует только шестнадцатеричные символы, 0-9,af . Для чего-то, что не похоже на hex, попробуйте следующее:

 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

Это не очень настраивается для создания интерфейса для пользователей, но для некоторых целей это нормально. Увеличьте количество символов, чтобы учесть отсутствие специальных символов.

  1. Создайте файл с этим кодом.
  2. Назовите это, как в комментариях.

     <?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); } } ?> 

Я создал более полный и безопасный скрипт паролей. Это создаст комбинацию из двух прописных, двух строчных, двух цифр и двух специальных символов. Всего 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); 
 <?php // We can generate without large code.. $length = 8; $chars = array_merge(range(0,9), range('a','z'),range('A','Z'),['!','@','#','$','%','&','*','?']); //$chars = array_merge(range(0,1), range('A','Z')); shuffle($chars); $code = implode(array_slice($chars, 0, $length)); $arr = array($code); $password = implode("",$arr); echo $password; 

Я просто использовал str_random(8) чтобы развернуть случайную строку для подтверждения кода.

Я хотел попробовать реализовать собственный «безопасный» и «случайный» генератор паролей.

Я думал, что было бы интересно и более гибко предоставлять параметр length и type функции.

Вот функция, которая выполняет несколько проверок, чтобы убедиться, что length не слишком короткая или длинная (также допускающая переменную длину). Он также позволяет выбирать кодировку паролей в параметре type .

Он возвращает значение null если length или type недопустимы, и использует функцию mt_rand() PHP, которая является более «случайной», чем rand() .

 <?php /** * Generates a random password with the given length and of the given type. * * @param int $length * @param string $type * @return string | null */ function random_password($length=8, $type='alpha_numeric') { if ($length < 1 || $length > 1024) return null; $lower = 'abcdefghijklmnopqrstuvwxy'; $upper = strtoupper($lower); $numbers = '1234567890'; $dash = '-'; $underscore = '_'; $symbols = '`~!@#$%^&*()+=[]\\{}|:";\'<>?,./'; switch ($type) { case 'lower': $chars = $lower; break; case 'upper': $chars = $upper; break; case 'numeric': $chars = $numbers; break; case 'alpha': $chars = $lower . $upper; break; case 'symbol': $chars = $symbols . $dash . $underscore; break; case 'alpha_numeric': $chars = $lower . $upper . $numbers; break; case 'alpha_numeric_dash': $chars = $lower . $upper . $numbers . $dash; break; case 'alpha_numeric_underscore': $chars = $lower . $upper . $numbers . $underscore; break; case 'alpha_numeric_dash_underscore': $chars = $lower . $upper . $numbers . $underscore . $dash; break; case 'all': $chars = $lower . $upper . $numbers . $underscore . $dash . $symbols; break; default: return null; } $min = 0; $max = strlen($chars) - 1; $password = ''; for ($i = 0; $i < $length; $i++) { $random = mt_rand($min, $max); $char = substr($chars, $random, 1); $password .= $char; } return $password; }