Генерация случайного пароля в php


Я пытаюсь сгенерировать случайный пароль на php.

Однако я получаю все "а", а возвращаемый тип имеет тип массива, и я хотел бы, чтобы это была строка. Есть идеи о том, как исправить код?

Спасибо.

function randomPassword() {
    $alphabet = "abcdefghijklmnopqrstuwxyzABCDEFGHIJKLMNOPQRSTUWXYZ0123456789";
    for ($i = 0; $i < 8; $i++) {
        $n = rand(0, count($alphabet)-1);
        $pass[$i] = $alphabet[$n];
    }
    return $pass;
}
Author: Scott Arciszewski, 2011-05-23

22 answers

Предупреждение о безопасности: 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

 229
Author: Neal, 2017-05-23 12:02:56

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

$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!

 98
Author: user3260409, 2014-10-03 13:42:21

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() полифайла , вероятно, безопаснее, чем написание собственной реализации.

Имея под рукой безопасный генератор случайных чисел, генерировать безопасную случайную строку проще, чем 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;
}
 96
Author: Scott Arciszewski, 2015-09-07 02:14:53

Крошечный код с 2 строкой.

Демонстрация: http://codepad.org/5rHMHwnH

function rand_string( $length ) {

    $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    return substr(str_shuffle($chars),0,$length);

}

echo rand_string(8);

С помощью rand_string вы можете определить, сколько символов будет создано.

 54
Author: BSQ, 2013-10-08 16:15:00

В одной строке:

substr(str_shuffle('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') , 0 , 10 )
 35
Author: Sandra, 2012-12-10 20:57:40

Если вы находитесь на 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;
}
 32
Author: PeeHaa, 2015-07-09 17:28:36

Ваш лучший выбор - это Библиотека 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() (что обычно требуется для конфиденциальной информации, такой как пароли, соли и ключи).

 25
Author: Madara Uchiha, 2015-07-06 12:58:50

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

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

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

 14
Author: phihag, 2011-05-25 08:05:16

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

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

Это ответ позволит обойти проблему count/strlen, поскольку безопасность сгенерированного пароля, по крайней мере, IMHO, превосходит то, как вы туда добираетесь. Я также собираюсь предположить, что 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, все пароли заканчивались бы одинаковым их количеством, так что злоумышленнику, у которого был доступ к результирующему паролю, нужно было бы угадать на 2 символа меньше.


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

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

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

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

 14
Author: jeteon, 2015-07-11 14:03:49

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

 12
Author: Explosion Pills, 2011-05-23 19:32:42

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);
    }
}
 11
Author: srcspider, 2015-07-08 10:52:59

Еще один (только для 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)), "=");
}
 9
Author: Askarel, 2013-03-08 11:04:42

Попробуйте сделать это с заглавными буквами, строчными буквами, цифрами и Специальными символами

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@ УД

 5
Author: Sanjeev, 2015-07-17 08:43:45

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

$password_string = '!@#$%*&abcdefghijklmnpqrstuwxyzABCDEFGHJKLMNPQRSTUWXYZ23456789';
$password = substr(str_shuffle($password_string), 0, 12);
 5
Author: Pablo Martinez, 2016-02-19 09:39:35

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

$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);
 3
Author: Cornelius Parkin, 2015-09-08 18:00:41

Это основано на другом ответе на этой странице, https://stackoverflow.com/a/21498316/525649

Этот ответ генерирует только шестнадцатеричные символы, 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

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

 3
Author: Adam, 2017-05-23 12:34:50
  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);
        }
    
    }
    
    ?>
    
 3
Author: waz, 2016-01-24 06:06:54

Быть немного умнее:

function strand($length){
  if($length > 0)
    return chr(rand(33, 126)) . strand($length - 1);
}

Проверьте это здесь.

 2
Author: Amir Forsati, 2018-04-03 21:51:21

Я создал более полный и безопасный сценарий ввода пароля. Это создаст комбинацию из двух прописных, двух строчных, двух цифр и двух специальных символов. Всего 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);
 1
Author: monrejames, 2016-11-04 22:04:05
<?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;
 -1
Author: Yagnesh bhalala, 2017-05-04 13:05:43

Если вам нужно 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);
 -1
Author: Joel Enanod Jr, 2018-07-02 07:53: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 = '`~!@#$%^&*()+=[]\\{}|:";\'<>?,./';

    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;
}
 -2
Author: bideowego, 2015-07-14 22:25:28