Я пытаюсь создать случайный пароль в 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 }
Я знаю, что вы пытаетесь сгенерировать свой пароль определенным образом, но вы можете также взглянуть на этот метод …
$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!
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
чтобы получить криптографически случайные данные.
Я собираюсь опубликовать ответ, потому что некоторые из существующих ответов близки, но имеют один из следующих:
Этот ответ count/strlen
проблему 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; }
Во второй части мы будем использовать 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
Это не очень настраивается для создания интерфейса для пользователей, но для некоторых целей это нормально. Увеличьте количество символов, чтобы учесть отсутствие специальных символов.
Назовите это, как в комментариях.
<?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; }