La bibliothèque standard de PHP 7 fournit la fonction random_bytes($length)
qui génèrent des octets pseudo-aléatoires cryptographiquement sûrs.
Exemple :
$bytes = random_bytes(20);
var_dump(bin2hex($bytes));
L'exemple ci-dessus produira quelque chose de similaire :
string(40) "5fe69c95ed70a9869d9f9af7d8400a6673bb9ce9"
Plus d'informations : http://php.net/manual/en/function.random-bytes.php
PHP 5 (obsolète)
Je cherchais justement comment résoudre ce même problème, mais je veux aussi que ma fonction crée un jeton qui puisse être utilisé pour récupérer le mot de passe. Cela signifie que je dois limiter la capacité du jeton à être deviné. Parce que uniqid
est basé sur le temps, et selon php.net "la valeur de retour est peu différente de microtime()", uniqid
ne répond pas aux critères. PHP recommande d'utiliser openssl_random_pseudo_bytes()
au lieu de générer des jetons cryptographiquement sécurisés.
Une réponse rapide, courte et précise est la suivante :
bin2hex(openssl_random_pseudo_bytes($bytes))
qui générera une chaîne aléatoire de caractères alphanumériques de longueur = $bytes * 2. Malheureusement, cette chaîne n'a qu'un alphabet de [a-f][0-9]
mais ça marche.
Voici la fonction la plus puissante que j'ai pu créer et qui répond aux critères (il s'agit d'une version implémentée de la réponse d'Erik).
function crypto_rand_secure($min, $max)
{
$range = $max - $min;
if ($range < 1) return $min; // not so random...
$log = ceil(log($range, 2));
$bytes = (int) ($log / 8) + 1; // length in bytes
$bits = (int) $log + 1; // length in bits
$filter = (int) (1 << $bits) - 1; // set all lower bits to 1
do {
$rnd = hexdec(bin2hex(openssl_random_pseudo_bytes($bytes)));
$rnd = $rnd & $filter; // discard irrelevant bits
} while ($rnd > $range);
return $min + $rnd;
}
function getToken($length)
{
$token = "";
$codeAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$codeAlphabet.= "abcdefghijklmnopqrstuvwxyz";
$codeAlphabet.= "0123456789";
$max = strlen($codeAlphabet); // edited
for ($i=0; $i < $length; $i++) {
$token .= $codeAlphabet[crypto_rand_secure(0, $max-1)];
}
return $token;
}
crypto_rand_secure($min, $max)
fonctionne comme un substitut à la rand()
ou mt_rand
. Il utilise openssl_random_pseudo_bytes pour aider à créer un nombre aléatoire entre $min et $max.
getToken($length)
crée un alphabet à utiliser dans le jeton et crée ensuite une chaîne de longueur $length
.
Source : http://us1.php.net/manual/en/function.openssl-random-pseudo-bytes.php#104322
1 votes
Tout ce dont vous avez besoin, ce sont des chaînes de caractères et des nombres aléatoires uniformément distribués.
12 votes
Hé Andrew, tu devrais choisir
Scott
comme réponse correcte. Scott utilise le générateur de nombres psudo-aléatoires à sécurité cryptographique (CSPRNG) d'OpenSSL, qui choisira la source d'entropie la plus sûre en fonction de votre plate-forme.3 votes
Si vous lisez ceci après 2015, s'il vous plaît, regardez ici : paragonie.com/blog/2015/07/ La plupart des réponses sont plus ou moins erronées...
0 votes
OpenSSL et
uniqid
ne sont pas sûrs. Utilisez quelque chose commeRandom::alphanumericString($length)
ouRandom::alphanumericHumanString($length)
.