web-dev-qa-db-fra.com

Générer un mot de passe aléatoire en php

J'essaie de générer un mot de passe aléatoire en php.

Cependant, je reçois tous les 'a et le type de retour est de type tableau et je voudrais que ce soit une chaîne. Des idées sur la façon de corriger le code?

Merci.

function randomPassword() {
    $alphabet = "abcdefghijklmnopqrstuwxyzABCDEFGHIJKLMNOPQRSTUWXYZ0123456789";
    for ($i = 0; $i < 8; $i++) {
        $n = Rand(0, count($alphabet)-1);
        $pass[$i] = $alphabet[$n];
    }
    return $pass;
}
173
nunos

Avertissement de sécurité : Rand() n'est pas un générateur de nombres pseudo-aléatoires cryptographiquement sécurisé. Cherchez ailleurs générant une chaîne pseudo-aléatoire sécurisée cryptographiquement en PHP .

Essayez ceci (utilisez strlen au lieu de count, car count sur une chaîne est toujours 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
}

Démo: http://codepad.org/UL8k4aYK

240
Neal

TL; DR:

  • Utilisez random_int() et la random_str() donnée ci-dessous.
  • Si vous n'avez pas random_int(), utilisez random_compat .

Explication:

Comme vous générez un mot de passe , vous devez vous assurer que le mot de passe que vous générez est imprévisible, et que le seul moyen de garantir que cette propriété est présente dans votre implémentation. est d'utiliser un générateur de nombres pseudo-aléatoires cryptographiquement sécurisé (CSPRNG).

L'exigence d'un CSPRNG peut être assouplie pour le cas général des chaînes aléatoires, mais pas lorsque la sécurité est impliquée.

La réponse simple, sécurisée et correcte à la génération de mot de passe dans PHP consiste à utiliser RandomLib et ne réinventez pas la roue. Cette bibliothèque a été auditée par des experts de la sécurité du secteur, ainsi que par moi-même.

Pour les développeurs qui préfèrent inventer leur propre solution, PHP 7.0.0 fournira random_int() à cet effet. Si vous êtes toujours sur PHP 5.x, nous avons écrit un PHP 5 polyfill pour random_int() afin que vous puissiez utiliser la nouvelle API avant la sortie de PHP 7. . Utiliser notre random_int() polyfill est probablement plus sûr que d’écrire votre propre implémentation.

Avec un générateur d’entiers aléatoires sécurisé, générer une chaîne aléatoire sécurisée est plus facile que camembert:

<?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;
}
108
Scott Arciszewski

Je sais que vous essayez de générer votre mot de passe d'une manière spécifique, mais vous voudrez peut-être aussi regarder cette méthode ...

$bytes = openssl_random_pseudo_bytes(2);

$pwd = bin2hex($bytes);

Il provient du site php.net et crée une chaîne qui est deux fois plus longue que le nombre que vous avez entré dans la fonction openssl_random_pseudo_bytes. Donc, ce qui précède créerait un mot de passe de 4 caractères.

En bref...

$pwd = bin2hex(openssl_random_pseudo_bytes(4));

Créerait un mot de passe de 8 caractères.

Notez cependant que le mot de passe ne contient que les chiffres 0-9 et les lettres minuscules a-f!

105
user3260409

Petit code avec 2 lignes.

démo: http://codepad.org/5rHMHwnH

function Rand_string( $length ) {

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

}

echo Rand_string(8);

avec Rand_string vous pouvez définir combien de caractères seront créés.

52
BSQ

En une ligne:

substr(str_shuffle('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') , 0 , 10 )
36
Sandra

Si vous utilisez PHP7, vous pouvez utiliser la fonction 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;
}

Ancienne réponse ci-dessous:

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;
}
36
PeeHaa

Votre meilleur pari est le bibliothèque RandomLib de ircmaxell.

Exemple d'utilisation:

$factory = new RandomLib\Factory;
$generator = $factory->getGenerator(new SecurityLib\Strength(SecurityLib\Strength::MEDIUM));

$passwordLength = 8; // Or more
$randomPassword = $generator->generateString($passwordLength);

Il produit des chaînes qui sont plus fortement aléatoires que les fonctions aléatoires normales telles que shuffle() et Rand() (ce que vous voulez généralement pour les informations sensibles telles que les mots de passe, les sels et les clés).

26
Madara Uchiha

Je vais poster une réponse car certaines des réponses existantes sont proches mais ont l'une des suivantes:

  • un espace de caractère plus petit que vous ne le souhaitez, de sorte que le forçage brutal est plus facile ou que le mot de passe doit être plus long pour la même entropie
  • un RNG qui n'est pas considéré comme sûr sur le plan cryptographique
  • une exigence pour une bibliothèque tierce partie et j'ai pensé qu'il pourrait être intéressant de montrer ce qu'il faudrait faire pour le faire soi-même

Cette réponse contournera le problème _count/strlen_ car la sécurité du mot de passe généré, du moins à mon humble avis, transcende la manière dont vous y allez. Je vais aussi supposer que PHP> 5.3.0.

Décomposons le problème en parties constitutives qui sont:

  1. utiliser une source aléatoire aléatoire pour obtenir des données aléatoires
  2. utiliser ces données et les représenter comme une chaîne imprimable

Pour la première partie, PHP> 5.3.0 fournit la fonction openssl_random_pseudo_bytes . Notez que si la plupart des systèmes utilisent un algorithme cryptographiquement fort, vous devez vérifier si nous allons utiliser un wrapper:

_/**
 * @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;
}
_

Pour la deuxième partie, nous utiliserons base64_encode car il faut une chaîne d'octets et produira une série de caractères dont l'alphabet est très proche de celui spécifié dans la question d'origine. Si cela ne nous dérangeait pas d'avoir _+_, _/_ et _=_ caractères apparaissent dans la chaîne finale et que nous voulions un résultat d'au moins _$n_ caractères, nous pourrions simplement utiliser:

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

Le facteur _3/4_ est dû au fait que le codage en base64 génère une chaîne dont la longueur est au moins supérieure au tiers de la chaîne d'octet. Le résultat sera exact pour que _$n_ soit un multiple de 4 et jusqu'à 3 caractères plus long sinon. Étant donné que les caractères supplémentaires sont principalement constitués du caractère de remplissage _=_, si, pour quelque raison que ce soit, nous étions contraints de définir une longueur exacte du mot de passe, nous pouvons le tronquer à la longueur souhaitée. Cela est dû en particulier au fait que pour un _$n_ donné, tous les mots de passe se terminent par le même nombre de ceux-ci, de sorte qu'un attaquant ayant accès à un mot de passe de résultat aurait jusqu'à 2 caractères de moins à deviner.


Pour obtenir un crédit supplémentaire, si nous voulions respecter les spécifications exactes, comme dans la question du PO, il nous faudrait alors travailler un peu plus. Je vais renoncer à l'approche de conversion de base ici et passer à une approche rapide et sale. Les deux doivent générer plus d’aléatoire que ce qui sera utilisé dans le résultat, en raison de la longueur de l’alphabet à 62 entrées.

Pour les caractères supplémentaires dans le résultat, nous pouvons simplement les supprimer de la chaîne résultante. Si nous commençons avec 8 octets dans notre chaîne d'octets, alors environ 25% des caractères base64 seront ces caractères "indésirables", de sorte que le simple rejet de ces caractères donne une chaîne non plus courte que celle souhaitée par l'OP. Ensuite, nous pouvons simplement le tronquer pour obtenir la longueur exacte:

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

Si vous générez des mots de passe plus longs, le caractère de remplissage _=_ forme une proportion de plus en plus petite du résultat intermédiaire, ce qui vous permet d'implémenter une approche plus légère si le vidage du pool d'entropie utilisé pour le PRNG est une préoccupation.

14
jeteon

Vous voulez strlen($alphabet), pas count de la constante alphabet (équivalent à 'alphabet').

Cependant, Rand n'est pas une fonction aléatoire appropriée à cette fin. Sa sortie peut facilement être prédite car il est implicitement ensemencé avec l'heure actuelle. De plus, Rand n'est pas sécurisé sur le plan cryptographique; il est donc relativement facile de déterminer son état interne à partir de la sortie.

Lisez plutôt /dev/urandom pour obtenir des données cryptographiquement aléatoires.

14
phihag

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

par exemple. e0m6ngefmj4

EDIT

Comme je l'ai mentionné dans les commentaires, la longueur signifie que les attaques par force brute fonctionneraient mieux contre elle que les attaques par minuterie; il n'est donc pas pertinent de s'inquiéter de "la sécurité du générateur aléatoire." La sécurité, en particulier pour ce cas d'utilisation, doit compléter la convivialité, de sorte que la solution ci-dessus est suffisamment adaptée au problème requis.

Cependant, juste au cas où vous tomberiez sur cette réponse en cherchant un générateur de chaîne aléatoire sécurisé (comme je suppose, d'après certaines personnes, en fonction des réponses), pour générer des jetons, voici à quoi ressemblerait un générateur de tels codes:

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
srcspider

Ceci est fondamentalement le même que le beaucoup plus simple substr(md5(uniqid()), 0, 8);

11
Explosion Pills

Un autre (Linux uniquement)

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
Askarel

Être un peu plus intelligent:

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

vérifiez-le ici .

8
Amir Forsati

Essayez ceci avec des lettres majuscules, des petites lettres, des caractères numériques et des caractères spéciaux

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
}

Disons que nous avons besoin de 10 Digit Pass

echo generatePassword(10);  

Exemple de sortie (s):

, IZCQ_IV\7

@wlqsfhT (d

1! 8 + 1\4 @ uD

6
Sanjeev

Utilisez ce code simple pour générer un mot de passe med-strong 12 longueur

$password_string = '!@#$%*&abcdefghijklmnpqrstuwxyzABCDEFGHJKLMNPQRSTUWXYZ23456789';
$password = substr(str_shuffle($password_string), 0, 12);
6
Pablo Martinez
  1. Créez un fichier contenant ce code.
  2. Appelez ça comme dans les commentaires.

    <?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
waz

Quick One. Format simple, propre et cohérent si c'est ce que vous voulez

$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
Cornelius Parkin

Ceci est basé sur une autre réponse de cette page, https://stackoverflow.com/a/21498316/525649

Cette réponse ne génère que des caractères hexadécimaux, 0-9,a-f. Pour quelque chose qui ne ressemble pas à un sortilège, essayez ceci:

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 renvoie un plus grand nombre de caractères alphanumériques
  • rtrim supprime le = parfois à la fin

Exemples:

  • 32eFVfGDg891Be5e7293e54z1D23110M3ZU3FMjb30Z9a740Ej0jz4
  • b280R72b48eOm77a25YCj093DE5d9549Gc73Jg8TdD9Z0Nj4b98760
  • 051b33654C0Eg201cfW0e6NA4b9614ze8D2FN49E12Y0zY557aUCb8
  • y67Q86ffd83G0z00M0Z152f7O2ADcY313Gd7a774fc5FF069zdb5b7

Ce n'est pas très configurable pour créer une interface pour les utilisateurs, mais pour des raisons bien définies. Augmentez le nombre de caractères pour tenir compte du manque de caractères spéciaux.

3
Adam

J'ai créé un script de mot de passe plus complet et sécurisé. Cela créera une combinaison de deux lettres majuscules, deux lettres minuscules, deux chiffres et deux caractères spéciaux. Total 8 caractères.

$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);
2
monrejames
//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
0
hakiko

Génère un mot de passe fort de longueur 8 contenant au moins une lettre minuscule, une lettre majuscule, un chiffre et un caractère spécial. Vous pouvez aussi changer la longueur dans le code.

function checkForCharacterCondition($string) {
    return (bool) preg_match('/(?=.*([A-Z]))(?=.*([a-z]))(?=.*([0-9]))(?=.*([~`\!@#\$%\^&\*\(\)_\{\}\[\]]))/', $string);
}

$j = 1;

function generate_pass() {
    global $j;
    $allowedCharacters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ~`!@#$%^&*()_{}[]';
    $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();
0
Zihad Ul Islam