Создание случайного пароля в php
Я пытаюсь создать случайный пароль в php.
Однако я получаю все 'a и возвращаемый тип массива типов, и я бы хотел, чтобы это была строка. Любые идеи о том, как исправить код?
Спасибо.
function randomPassword() {
$alphabet = "abcdefghijklmnopqrstuwxyzABCDEFGHIJKLMNOPQRSTUWXYZ0123456789";
for ($i = 0; $i < 8; $i++) {
$n = rand(0, count($alphabet)-1);
$pass[$i] = $alphabet[$n];
}
return $pass;
}
Ответы
Ответ 1
Предупреждение о безопасности: 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
Ответ 2
TL; DR:
- Используйте
random_int()
и заданный random_str()
ниже. - Если у вас нет
random_int()
, используйте random_compat.
Объяснение:
Поскольку вы генерируете пароль, вам нужно убедиться, что сгенерированный вами пароль непредсказуем, и единственный способ убедиться, что это свойство присутствует в вашей реализации, - это использовать криптографически безопасный генератор псевдослучайных чисел (CSPRNG).
Требование к CSPRNG может быть смягчено для общего случая случайных строк, но не когда речь идет о безопасности.
Простой, безопасный и правильный ответ на генерацию пароля в PHP - это использовать RandomLib и не изобретать велосипед. Эта библиотека была проверена экспертами по безопасности отрасли, а также я.
Для разработчиков, которые предпочитают изобретать собственное решение, PHP 7.0.0 предоставит random_int()
для этой цели. Если вы все еще используете PHP 5.x, мы написали PHP5 polyfill для random_int()
чтобы вы могли использовать новый API до выпуска PHP 7. Использование нашего random_int()
вероятно, безопаснее, чем написание собственной реализации.
С помощью надежного генератора случайных целых чисел создать безопасную случайную строку проще, чем 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;
}
Ответ 3
Я знаю, что вы пытаетесь сгенерировать свой пароль определенным образом, но вы можете также взглянуть на этот метод...
$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 и буквы малой буквы a-f!
Ответ 4
Маленький код с 2 строкой.
demo: http://codepad.org/5rHMHwnH
function rand_string( $length ) {
$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
return substr(str_shuffle($chars),0,$length);
}
echo rand_string(8);
с помощью rand_string вы можете определить, сколько символов будет создано.
Ответ 5
Если вы находитесь на PHP7, вы можете использовать функцию random_int()
:
function generate_password($length = 20){
$chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.
'0123456789`[email protected]#$%^&*()_+,./<>?;:[]{}\|';
$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`[email protected]#$%^&*()_+,./<>?;:[]{}\|';
$str = '';
$max = strlen($chars) - 1;
for ($i=0; $i < $length; $i++)
$str .= $chars[mt_rand(0, $max)];
return $str;
}
Ответ 6
В одной строке:
substr(str_shuffle('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') , 0 , 10 )
Ответ 7
Ваш лучший выбор - библиотека 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()
(что вы обычно хотите для чувствительной информации, такой как пароли, соли и ключи).
Ответ 8
Вы хотите strlen($alphabet)
, а не count
константы alphabet
(эквивалентно 'alphabet'
).
Однако rand
не является подходящей случайной функцией для этой цели. Его выход можно легко предсказать, поскольку он неявно посеян с текущим временем. Кроме того, rand
не является криптографически безопасным; поэтому относительно легко определить его внутреннее состояние с выхода.
Вместо этого прочитайте из /dev/urandom
, чтобы получить криптографически случайные данные.
Ответ 9
Я собираюсь опубликовать ответ, потому что некоторые из существующих ответов близки, но имеют один из следующих вариантов:
- меньшее пространство символов, чем вы хотели, чтобы либо принудительное форматирование было проще, либо пароль был длиннее для той же энтропии
- a RNG, который не считается криптографически защищенным
- требование для некоторой сторонней библиотеки, и я подумал, что может быть интересно показать, что это может сделать для этого.
Этот ответ обойдет проблему 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, является проблемой.
Ответ 10
Это в основном то же самое, что и гораздо проще substr(md5(uniqid()), 0, 8);
Ответ 11
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);
}
}
Ответ 12
Другой (только для 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)), "=");
}
Ответ 13
Быть немного умнее:
function strand($length){
if($length > 0)
return chr(rand(33, 126)) . strand($length - 1);
}
проверьте это здесь.
Ответ 14
Попробуйте это с помощью писем, маленьких букв, цифр и специальных символов
function generatePassword($_len) {
$_alphaSmall = 'abcdefghijklmnopqrstuvwxyz'; // small letters
$_alphaCaps = strtoupper($_alphaSmall); // CAPITAL LETTERS
$_numerics = '1234567890'; // numerics
$_specialChars = '`[email protected]#$%^&*()-_=+]}[{;:,<.>/?\'"\|'; // 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 (d
1! 8 + 1\4 @UD
Ответ 15
Используйте этот простой код для генерации надежного пароля длиной 12
$password_string = '[email protected]#$%*&abcdefghijklmnpqrstuwxyzABCDEFGHJKLMNPQRSTUWXYZ23456789';
$password = substr(str_shuffle($password_string), 0, 12);
Ответ 16
Быстрый. Простой, чистый и согласованный формат, если это то, что вы хотите
$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);
Ответ 17
Это основано на другом ответе на этой странице, fooobar.com/questions/6881/...
Этот ответ генерирует только шестнадцатеричные символы, 0-9,a-f
. Для чего-то, что не похоже на 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
Это не очень настраивается для создания интерфейса для пользователей, но для некоторых целей, которые в порядке. Увеличьте количество символов, чтобы учесть отсутствие специальных символов.
Ответ 18
- Создайте файл с этим кодом.
-
Назовите это, как в комментариях.
<?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 = "[email protected]#$%^&*(){}/?,><";
return substr(str_shuffle($chars),0,$length);
}
private function hashPwd($pwd) {
return hash('sha256', $pwd);
}
}
?>
Ответ 19
Я создал более полный и безопасный пароль script. Это создаст комбинацию из двух прописных, двух строчных, двух цифр и двух специальных символов. Всего 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);
Ответ 20
//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
Ответ 21
Создает надежный пароль длиной 8, содержащий как минимум одну строчную букву, одну заглавную букву, одну цифру и один специальный символ. Вы можете изменить длину в коде тоже.
function checkForCharacterCondition($string) {
return (bool) preg_match('/(?=.*([A-Z]))(?=.*([a-z]))(?=.*([0-9]))(?=.*([~'\[email protected]#\$%\^&\*\(\)_\{\}\[\]]))/', $string);
}
$j = 1;
function generate_pass() {
global $j;
$allowedCharacters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ~'[email protected]#$%^&*()_{}[]';
$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();
Ответ 22
<?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;
Ответ 23
Если вы хотите 8 символов с 1 заглавной и 1 цифрой.
$p_lc_letters = substr(str_shuffle('abcdefghijklmnopqrstuvwxyz'), 0, 6); // Generate 6 lowercase letters
$p_uc_letters = substr(str_shuffle('ABCDEFGHIJKLMNOPQRSTUVWXYZ'), 0, 1); // Generate 1 uppercase letter
$p_numbers = substr(str_shuffle('0123456789'), 0, 1); // Generate 1 number
echo $password = substr(str_shuffle($p_lc_letters.''.$p_uc_letters.''.$p_numbers), 0, 8);
Ответ 24
Я хотел попробовать реализовать собственный "безопасный" и "случайный" генератор паролей.
Я думал, что было бы интереснее и гибче предоставить параметр length
и type
для функции.
Вот функция, которая выполняет несколько проверок, чтобы убедиться, что length
не слишком короткий или длинный (также допускающий переменную длину). Он также позволяет выбирать кодировку паролей в параметре type
.
Возвращает null
, если length
или type
являются недопустимыми и использует функцию PHP mt_rand()
, которая более "случайная", чем 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 = '`[email protected]#$%^&*()+=[]\\{}|:";\'<>?,./';
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;
}