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;
}
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
}
random_int()
et la random_str()
donnée ci-dessous.random_int()
, utilisez random_compat .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;
}
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!
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.
En une ligne:
substr(str_shuffle('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') , 0 , 10 )
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;
}
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).
Je vais poster une réponse car certaines des réponses existantes sont proches mais ont l'une des suivantes:
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:
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.
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.
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);
}
}
Ceci est fondamentalement le même que le beaucoup plus simple substr(md5(uniqid()), 0, 8);
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)), "=");
}
Être un peu plus intelligent:
function strand($length){
if($length > 0)
return chr(Rand(33, 126)) . strand($length - 1);
}
vérifiez-le ici .
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
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);
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);
}
}
?>
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);
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ériquesrtrim
supprime le =
parfois à la finExemples:
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.
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);
//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
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();