Генерация случайного пароля в 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;
}
779   22  

22 ответов:

предупреждение: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 и маленькие заглавные буквы a-f!

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, мы написали a PHP 5 polyfill for 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.

demo: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 для получения криптографически случайные данные.

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

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

этот ответ позволит обойти 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))));

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


для дополнительного кредита, если бы мы хотели встретить точную спецификацию, как в вопросе 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

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

еще один (только для 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-значный проход

echo generatePassword(10);  

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

, IZCQ_IV\7

@wlqsfhT(d

1!8+1\4@uD

используйте этот простой код для генерации med-strong password 12 length

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

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

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

немного умнее:

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

проверить здесь.

Я создал более полный и безопасный скрипт пароль. Это создаст комбинацию из двух прописных, двух строчных, двух цифр и двух специальных символов. Всего 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;

Если вы хотите 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);

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

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

Comments

    Ничего не найдено.