Générateur de chaînes aléatoires PHP

815

J'essaie de créer une chaîne aléatoire en PHP, et je n'obtiens absolument aucune sortie avec ceci:

<?php
    function RandomString()
    {
        $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
        $randstring = '';
        for ($i = 0; $i < 10; $i++) {
            $randstring = $characters[rand(0, strlen($characters))];
        }
        return $randstring;
    }

    RandomString();
    echo $randstring;

Qu'est-ce que je fais mal?

Captain Lightning
la source
241
Ma solution d'une ligne pour générer une chaîne courte est substr (md5 (rand ()), 0, 7); bonne chance ...
tasmaniski
5
@tasmaniski .. Votre solution est ok .. Mais c'est moins aléatoire! Dans votre exemple, le nombre de chaînes aléatoires pouvant être générées est limité par la taille de l'entier. (2 ^ 32) au maximum .. Dans le cas de l'autre solution, vous pouvez générer (62 ^ 8) .. Dans le cas où je veux des chaînes plus grandes, alors le nombre de chaînes distinctes reste au maximum 2 ^ 32, mais dans le autre solution, il augmente à (62 ^ n) ..
Manu
9
Vous avez oublié d'ajouter chaque nouveau caractère généré à la chaîne. Vous êtes en train de l'écraser tel quel. Doit être $ randstring. = $ Caractères ..
Spock
3
@CaptainLightning Pouvez-vous s'il vous plaît échanger la réponse acceptée pour l'une des plus sécurisées? :)
Scott Arciszewski
2
strlen($characters)=> strlen($characters) - 1- la longueur de la chaîne commence par 1
Zippp

Réponses:

1395

Pour répondre spécifiquement à cette question, deux problèmes:

  1. $randstring n'est pas dans la portée lorsque vous l'écho.
  2. Les personnages ne sont pas concaténés ensemble dans la boucle.

Voici un extrait de code avec les corrections:

function generateRandomString($length = 10) {
    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $charactersLength = strlen($characters);
    $randomString = '';
    for ($i = 0; $i < $length; $i++) {
        $randomString .= $characters[rand(0, $charactersLength - 1)];
    }
    return $randomString;
}

Sortez la chaîne aléatoire avec l'appel ci-dessous:

// Echo the random string.
// Optionally, you can give it a desired string length.
echo generateRandomString();

Veuillez noter que cela génère des chaînes aléatoires prévisibles. Si vous souhaitez créer des jetons sécurisés, consultez cette réponse .

Stephen Watkins
la source
34
@FranciscoPresencia, Il vaut mieux "gaspiller" une variable supplémentaire que d'appeler une méthode dans la condition de comparaison d'une boucle.
Rico Sonntag
200
Tout ce travail, pourquoi pas juste quelque chose comme ça substr(str_shuffle(MD5(microtime())), 0, 10);?
SpYk3HH
4
Merci pour le code, mais veuillez changer rand()pour mt_rand(). J'ai utilisé votre méthode et vécu une tonne de collisions avec des noms.
Nate
5
@FranciscoPresencia avez-vous une idée à quel point c'est terriblement inefficace? Vous vérifiez la longueur d'une chaîne deux fois par itération! Le strlen à l'intérieur de la boucle doit également être mis en cache dans une variable avant d'entrer dans la boucle.
developerbmw
4
Ce n'est pas une bonne solution. Les chaînes générées seront prévisibles. :(
Scott Arciszewski
370

Remarque: str_shuffle()utilise en interne rand(), ce qui ne convient pas à des fins de cryptographie (par exemple, générer des mots de passe aléatoires). Vous voulez plutôt un générateur de nombres aléatoires sécurisé . Il ne permet pas non plus aux personnages de se répéter.

Encore une façon.

MISE À JOUR (maintenant cela génère n'importe quelle longueur de chaîne):

function generateRandomString($length = 10) {
    return substr(str_shuffle(str_repeat($x='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', ceil($length/strlen($x)) )),1,$length);
}

echo  generateRandomString();  // OR: generateRandomString(24)

C'est ça. :)

A. Cheshirov
la source
64
+1 pour la réponse la plus courte :). Mais ce n'est pas la meilleure réponse pour chaque cas d'utilisation. Ce code produira des chaînes où chaque caractère n'apparaîtra pas plus d'une fois (le rendant ainsi plus faible pour les attaques par force brute) et ne produira rien de plus de 62 caractères.
David
17
Ne faites pas ça, c'est extrêmement faible. Plus vous allongerez votre chaîne aléatoire, plus elle sera faible.
Abhi Beckert
23
C'est peut-être faible, mais c'est rapide et facile. Selon le cas d'utilisation, c'est très bien - je l'ai utilisé parce que je n'avais pas besoin de sécurité ou de force; juste un mélange rapide. J'écris un test unitaire, et cela me donne une entrée aléatoire appropriée pour tester avec.
SDC
23
@FranciscoPresencia la raison pour laquelle il n'est pas sécurisé est parce qu'il n'utilise jamais deux fois le même caractère. Cela en fait un terrible générateur de mots de passe. S'il vous plaît tout le monde arrête de voter cela, il est totalement dangereux ne doit jamais être utilisé. Au fur et à mesure que le mot de passe s'allonge, le nombre de caractères que vous devez tester en force brute diminue car vous ne prenez pas la peine de tester un caractère précédemment utilisé.
Abhi Beckert
8
@FranciscoPresencia: J'appuie vos commentaires sur le fait d'éviter d'utiliser ceci pour des mots de passe aléatoires. Cependant, je ne suis pas d'accord pour dire que cette réponse ne devrait pas être positive. J'ai plus-un pour cette option car c'est une solution efficace sur une ligne pour générer des chaînes aléatoires (le sujet d'origine de cette question).
bwright
331

Il existe de nombreuses réponses à cette question, mais aucune d'entre elles ne tire parti d'un générateur de nombres pseudo-aléatoires cryptographiquement sécurisé (CSPRNG).

La réponse simple, sûre et correcte consiste à utiliser RandomLib et à ne pas réinventer la roue.

Pour ceux d'entre vous qui insistent pour inventer votre propre solution, PHP 7.0.0 fournira random_int()à cet effet; si vous êtes toujours sur PHP 5.x, nous avons écrit un polyfill PHP 5 pourrandom_int() que vous puissiez utiliser la nouvelle API avant même de passer à PHP 7.

Générer en toute sécurité des nombres entiers aléatoires en PHP n'est pas une tâche triviale. Vous devriez toujours vérifier avec vos experts en cryptographie StackExchange résidents avant de déployer un algorithme local en production.

Avec un générateur d'entiers sécurisé en place, générer une chaîne aléatoire avec un CSPRNG est une promenade dans le parc.

Création d'une chaîne aléatoire et sécurisée

/**
 * Generate a random string, using a cryptographically secure 
 * pseudorandom number generator (random_int)
 *
 * This function uses type hints now (PHP 7+ only), but it was originally
 * written for PHP 5 as well.
 * 
 * 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(
    int $length = 64,
    string $keyspace = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
): string {
    if ($length < 1) {
        throw new \RangeException("Length must be a positive integer");
    }
    $pieces = [];
    $max = mb_strlen($keyspace, '8bit') - 1;
    for ($i = 0; $i < $length; ++$i) {
        $pieces []= $keyspace[random_int(0, $max)];
    }
    return implode('', $pieces);
}

Utilisation :

$a = random_str(32);
$b = random_str(8, 'abcdefghijklmnopqrstuvwxyz');
$c = random_str();

Démo : https://3v4l.org/IMJGF (Ignorez les échecs de PHP 5; il a besoin de random_compat)

Scott Arciszewski
la source
3
Au début de la fonction ajouter $keyspace = str_shuffle($keyspace );pour plus de sécurité
Jevgenij Dmitrijev
13
Qu'entendez-vous par «pour plus de sécurité»? Nous utilisons déjà un générateur de nombres aléatoires sécurisé.
Scott Arciszewski
5
@JGEstiot La création de chaînes aléatoires en toute sécurité nécessite un caractère aléatoire cryptographiquement sécurisé. Quelqu'un qui cherche "comment générer des chaînes aléatoires en PHP" est mieux servi par une réponse sécurisée qu'une réponse non sécurisée.
Scott Arciszewski
1
@ Scott Arciszewski Vous n'avez pas besoin de créer de chaînes cryptographiques aléatoires chaque fois que vous créez des chaînes aléatoires. La question était de créer des chaînes aléatoires et cela n'a rien à voir avec la sécurité. Vous avez supposé que la chaîne allait être utilisée dans un contexte sensible à la sécurité et vous ajoutez une couche de complexité qui décourage le cœur de la question.
JG Estiot
45
Utiliser random_int()au lieu de rand()ou mt_rand()n'ajoute aucune complexité pour le développeur. En même temps, cela leur donne une plus grande sécurité. Les personnes qui viennent sur StackOverflow à la recherche de solutions rapides peuvent ne pas savoir si la chose qu'elles construisent doit être sécurisée ou non. Si nous leur donnons des réponses sécurisées par défaut, ils créent un Internet plus sécurisé même si, de leur point de vue, c'est totalement accidentel. Pourquoi vous opposeriez-vous à cet objectif est un mystère pour moi.
Scott Arciszewski
156

Cela crée une chaîne hexadécimale longue de 20 caractères:

$string = bin2hex(openssl_random_pseudo_bytes(10)); // 20 chars

En PHP 7 ( random_bytes () ):

$string = base64_encode(random_bytes(10)); // ~14 characters, includes /=+
// or
$string = substr(str_replace(['+', '/', '='], '', base64_encode(random_bytes(32))), 0, 32); // 32 characters, without /=+
// or
$string = bin2hex(random_bytes(10)); // 20 characters, only 0-9a-f
Rudie
la source
Veuillez noter que vous openssl_random_pseudo_bytes()n'avez pas utilisé d'algorithme cryptographiquement puissant jusqu'à php 5.6. Bogue
acidtv
Notez également que la plus petite chaîne que cela peut faire est de longueur 2. Si vous passez une longueur d'octet de 1 ou moins, openssl_random_pseudo_bytes()vous n'obtiendrez rien en retour. Notez également que lors de l'utilisation bin2hex(openssl_random_pseudo_bytes($length / 2))puisque vous travaillez avec des entiers, il supprimera automatiquement le modulo et utilisera le prochain plus petit multiple de 2. Ainsi, $length = 19produira une chaîne de longueur 18.
Nathan F.
Proposition de l' utiliser comme contenu du fichier qui peut être ouvert par fgets($fp, 1024)et chaque éditeur de fichiers qui a des problèmes avec des lignes très longues: function string_rand($len, $split="\n") { return substr(chunk_split(bin2hex(openssl_random_pseudo_bytes(ceil($len / 2))), 1023, $split), 0, $len); }Set $splitpour nulls'il doit renvoyer une seule ligne. Par cela, vous pouvez l'utiliser pour les deux cas.
mgutt
J'aime vraiment la solution random_bytes pour PHP 7, mais si vous avez besoin que la chaîne soit un certain nombre de caractères, quelque chose comme ça fonctionnerait? $string = substr(base64_encode(random_bytes($size)), 0, $size);
Programster
C'est sans aucun doute la meilleure solution. Prend très peu de place et est super facile à comprendre.
Matthew Campbell
92

@tasmaniski: votre réponse a fonctionné pour moi. J'ai eu le même problème, et je le proposerais à ceux qui recherchent toujours la même réponse. Le voici de @tasmaniski:

<?php 
    $random = substr(md5(mt_rand()), 0, 7);
    echo $random;
?>

Voici une vidéo sur YouTube nous montrant comment créer un nombre aléatoire

Humphrey
la source
6
si votre chaîne est basée uniquement sur un entier aléatoire, pourquoi ne pas simplement utiliser l'entier aléatoire? ils ne vont pas plus loin en hachant la botte de foin ... et en coupant le hachage de vous, vous déminez la petite entropie avec laquelle vous deviez commencer.
The Surrican
4
Gardez à l'esprit md5que la limite est de 30 caractères et toujours les caractères en minuscules.
fyrye
3
De plus, rand () ne doit pas être utilisé pour la cryptographie. Si vous cherchez à générer une chaîne sonore cryptographique, utilisez openssl_random_pseudo_bytes .
mattkgross
md5(rand())ne propose que 2 ^ 32 valeurs possibles. Cela signifie qu'après, en moyenne, 2 ^ 16 chaînes aléatoires, vous vous attendez à ce qu'une répétition.
Scott Arciszewski
2
Eh bien ... je parierais que l'OP ne parle pas de "chaînes aléatoires en toute sécurité". Cette solution est compacte, facile et jolie à retenir, pour les bons cas d'utilisation. Et, si vous devez vous occuper des collisions possibles, pourquoi ne pas ajouter / ajouter un horodatage à la chaîne aléatoire? :)
Erenor Paz
46

Selon votre application (je voulais générer des mots de passe), vous pouvez utiliser

$string = base64_encode(openssl_random_pseudo_bytes(30));

Étant base64, ils peuvent contenir =ou -aussi bien que les caractères demandés. Vous pouvez générer une chaîne plus longue, puis la filtrer et la couper pour la supprimer.

openssl_random_pseudo_bytessemble être le moyen recommandé pour générer un nombre aléatoire approprié en php. Pourquoi randn'utilise pas /dev/randomje ne sais pas.

rjmunro
la source
2
rand n'utilise pas / dev / urandom car il n'est disponible que dans des environnements de type posix et n'est pas portable.
MacroMan
3
@MacroMan Mais openssl_random_pseudo_bytes() est portable.
Ja͢ck
Si vous souhaitez supprimer les caractères base64 supplémentaires, essayez ceci: gist.github.com/zyphlar/7217f566fc83a9633959
willbradley
3
Ce n'est pas faux, mais je vous conseillerais d'être prudent dans la façon dont vous supprimez les caractères indésirables. Voir cette demande de pull sur le serveur OAuth2 de la ligue PHP , par exemple.
Scott Arciszewski
C'est l'une des meilleures réponses. Dommage qu'il n'ait pas plus de soutien. Je recommanderais cependant de modifier votre réponse pour une meilleure gestion des caractères indésirables.
jcuenod
28

Voici une simple ligne qui génère une vraie chaîne aléatoire sans aucune boucle de niveau de script ni utilisation de bibliothèques OpenSSL.

echo substr(str_shuffle(str_repeat('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', mt_rand(1,10))), 1, 10);

Pour le décomposer afin que les paramètres soient clairs

// Character List to Pick from
$chrList = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

// Minimum/Maximum times to repeat character List to seed from
$chrRepeatMin = 1; // Minimum times to repeat the seed string
$chrRepeatMax = 10; // Maximum times to repeat the seed string

// Length of Random String returned
$chrRandomLength = 10;

// The ONE LINE random command with the above variables.
echo substr(str_shuffle(str_repeat($chrList, mt_rand($chrRepeatMin,$chrRepeatMax))), 1, $chrRandomLength);

Cette méthode fonctionne en répétant au hasard la liste des caractères, puis mélange la chaîne combinée et renvoie le nombre de caractères spécifié.

Vous pouvez encore randomiser cela, en randomisant la longueur de la chaîne retournée, en la remplaçant $chrRandomLengthpar mt_rand(8, 15)(pour une chaîne aléatoire entre 8 et 15 caractères).

Kraang Prime
la source
désolé de le dire, mais quand un personnage a été sélectionné, sa probabilité de réapparaître n'est pas aussi élevée que les autres personnages restant dans le pool. pas de vrai hasard ici ...
The Surrican
@TheSurrican - Vous vous tromperiez dans cette déclaration. Tous les personnages ont une probabilité égale en utilisant cet algorithme et sont donc vraiment aléatoires. Ceci est assuré en répétant la chaîne chrList $ chrRepeatMax, et la magie se produit vraiment dans str_shuffle qui détermine le caractère aléatoire.
Kraang Prime
Tous les caractères n'apparaîtraient qu'une seule fois et il est très enclin à deviner bruteforce
venimus
@venimus C'est incorrect. La chaîne de caractères est dupliquée pour autant de caractères que vous le souhaitez (voir $chrRepeatMaxet $chrRepeatMin) - donc une chaîne de 10 caractères, pourrait (peu probable, mais possible), être "aaaaaaaaaaa".
Kraang Prime
@SanuelJackson Désolé d'avoir mal commenté. J'ai mis le commentaire sur la mauvaise réponse. Tu as raison! En fait, j'ai utilisé votre "astuce", mais je n'ai pas utilisé mt_rand, car il est inutile à mon humble avis. Cela n'ajoute rien à l'entropie. Juste utilisé const avec la longueur max.
venimus
25
function generateRandomString($length = 15)
{
    return substr(sha1(rand()), 0, $length);
}

Tada!

Savourer
la source
Gardez à l'esprit sha1que la limite est de 40 caractères et toujours les caractères en minuscules.
fyrye
3
Les chaînes sha1 ne sont pas aléatoires, certains caractères apparaîtront plus fréquemment que d'autres. Il serait imprudent de l'utiliser dans les cas où vous voulez vraiment le hasard comme pour les mots de passe.
Kit Sunde
1
@KitSunde - oui, sha n'est pas aléatoire, rand () est aléatoire. Et sha est parfaitement bien pour ce qui est nécessaire ici. OP n'a pas besoin de niveau de chiffrement aléatoire.
Davor
@Davor rant()être aléatoire n'a pas d'importance lorsque sha n'est pas réparti également. Si vous sélectionnez au hasard dans une distribution inégale, vous obtenez exactement la même distribution inégale. Ce n'est pas le caractère aléatoire du "niveau crypto" que je souligne, si c'était le cas, vous ne devriez pas non plus l'utiliser rand(). Il faut un effort minimal pour extraire une distribution uniforme comme dans la réponse acceptée et c'est aussi aléatoire que rand () qui est raisonnablement.
Kit Sunde
@KitSunde - cela ne fait littéralement aucune différence à la fin. C'est exactement la définition de la suringénierie et du placage à l'or.
Davor
24

Une meilleure façon de mettre en œuvre cette fonction est:

function RandomString($length) {
    $keys = array_merge(range(0,9), range('a', 'z'));

    $key = "";
    for($i=0; $i < $length; $i++) {
        $key .= $keys[mt_rand(0, count($keys) - 1)];
    }
    return $key;
}

echo RandomString(20);

mt_randest plus aléatoire selon ceci et cela en PHP 7. La randfonction est un alias de mt_rand.

Rathienth Baskaran
la source
1
Attention: mt_randne génère pas de valeurs cryptographiquement sécurisées. Pour cela, vous devez utiliser PHP7 random_intou random_bytes.
jchook
18

$randstringdans la portée de la fonction n'est pas la même que celle où vous l'appelez. Vous devez affecter la valeur de retour à une variable.

$randstring = RandomString();
echo $randstring;

Ou faites simplement écho à la valeur de retour:

echo RandomString();

De plus, dans votre fonction, vous avez une petite erreur. Dans la boucle for, vous devez utiliser .=pour que chaque caractère soit ajouté à la chaîne. En l'utilisant, =vous l'écrasez avec chaque nouveau caractère au lieu de l'ajouter.

$randstring .= $characters[rand(0, strlen($characters))];
BoltClock
la source
14

Tout d'abord, vous définissez l'alphabet que vous souhaitez utiliser:

$alphanum = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
$special  = '~!@#$%^&*(){}[],./?';
$alphabet = $alphanum . $special;

Ensuite, utilisez openssl_random_pseudo_bytes()pour générer des données aléatoires appropriées:

$len = 12; // length of password
$random = openssl_random_pseudo_bytes($len);

Enfin, vous utilisez ces données aléatoires pour créer le mot de passe. Étant donné que chaque caractère $randompeut être chr(0)jusqu'à chr(255), le code utilise le reste après la division de sa valeur ordinale avec $alphabet_lengthpour s'assurer que seuls les caractères de l'alphabet sont sélectionnés (notez que cela faussera le caractère aléatoire):

$alphabet_length = strlen($alphabet);
$password = '';
for ($i = 0; $i < $len; ++$i) {
    $password .= $alphabet[ord($random[$i]) % $alphabet_length];
}

Alternativement, et généralement mieux, utilisez RandomLib et SecurityLib :

use SecurityLib\Strength;

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

$password = $generator->generateString(12, $alphabet);
Ja͢ck
la source
L'utilisation de l'opérateur modulo %produira une sortie biaisée. Cependant, fort +1 pour RandomLib. Ne réinventez pas la roue.
Scott Arciszewski
1
Oui, la nouvelle fonction random_int () est sympa: D
Ja͢ck
11

Méthodes courtes ..

Voici la méthode la plus courte pour générer la chaîne aléatoire

<?php
echo $my_rand_strng = substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), -15); 

echo substr(md5(rand()), 0, 7);

echo str_shuffle(MD5(microtime()));
?>
Punit Gajjar
la source
10

J'y ai testé les performances des fonctions les plus populaires, le temps nécessaire pour générer 1'000'000 chaînes de 32 symboles sur ma box est:

2.5 $s = substr(str_shuffle(str_repeat($x='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', ceil($length/strlen($x)) )),1,32);
1.9 $s = base64_encode(openssl_random_pseudo_bytes(24));
1.68 $s = bin2hex(openssl_random_pseudo_bytes(16));
0.63 $s = base64_encode(random_bytes(24));
0.62 $s = bin2hex(random_bytes(16));
0.37 $s = substr(md5(rand()), 0, 32);
0.37 $s = substr(md5(mt_rand()), 0, 32);

Veuillez noter qu'il n'est pas important de savoir combien de temps il a réellement duré, mais lequel est plus lent et lequel est plus rapide afin que vous puissiez sélectionner en fonction de vos besoins, y compris la préparation à la cryptographie, etc.

substr () autour de MD5 a été ajouté par souci de précision si vous avez besoin d'une chaîne de moins de 32 symboles.

Par souci de réponse: la chaîne n'a pas été concaténée mais écrasée et le résultat de la fonction n'a pas été stocké.

Putnik
la source
Je pense que c'est la meilleure réponse. Merci!
NSukonny
10

PHP 7+ Générez des octets aléatoires cryptographiquement sécurisés à l'aide de la fonction random_bytes .

$bytes = random_bytes(16);
echo bin2hex($bytes);

Sortie possible

da821217e61e33ed4b2dd96f8439056c


PHP 5.3+ Générez des octets pseudo-aléatoires en utilisant la fonction openssl_random_pseudo_bytes .

$bytes = openssl_random_pseudo_bytes(16);
echo bin2hex($bytes);

Sortie possible

e2d1254506fbb6cd842cd640333214ad


Le meilleur cas d'utilisation pourrait être

function getRandomBytes($length = 16)
{
    if (function_exists('random_bytes')) {
        $bytes = random_bytes($length / 2);
    } else {
        $bytes = openssl_random_pseudo_bytes($length / 2);
    }
    return bin2hex($bytes);
}
echo getRandomBytes();

Sortie possible

ba8cc342bdf91143

Madan Sapkota
la source
Cela ne générera pas une chaîne avec la longueur donnée
Timberman
@Timberman va générer la longueur exacte maintenant.
Madan Sapkota
9

Un moyen très rapide est de faire quelque chose comme:

substr(md5(rand()),0,10);

Cela générera une chaîne aléatoire d'une longueur de 10 caractères. Bien sûr, certains pourraient dire que c'est un peu plus lourd du côté du calcul, mais de nos jours les processeurs sont optimisés pour exécuter l'algorithme md5 ou sha256 très rapidement. Et bien sûr, si la rand()fonction renvoie la même valeur, le résultat sera le même, avec 1/32767 chance d'être le même. Si la sécurité est le problème, passez simplement rand()àmt_rand()

Akatosh
la source
7
function rndStr($len = 64) {
     $randomData = file_get_contents('/dev/urandom', false, null, 0, $len) . uniqid(mt_rand(), true);
     $str = substr(str_replace(array('/','=','+'),'', base64_encode($randomData)),0,$len);
    return $str;
}
Руслан Ибрагимов
la source
4
Ce n'est pas portable; si vous essayez de l'exécuter dans un environnement non-posix, cela entraînera une erreur fatale.
Bryan Agee
7

Celui-ci a été tiré de sources d'administrateur :

/** Get a random string
* @return string 32 hexadecimal characters
*/
function rand_string() {
    return md5(uniqid(mt_rand(), true));
}

Administrateur , outil de gestion de base de données écrit en PHP.

userlond
la source
6

Fonction d'aide du framework Laravel 5

/**
 * Generate a "random" alpha-numeric string.
 *
 * Should not be considered sufficient for cryptography, etc.
 *
 * @param  int  $length
 * @return string
 */
function str_random($length = 16)
{
    $pool = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

    return substr(str_shuffle(str_repeat($pool, $length)), 0, $length);
}
artnikpro
la source
4
"Ne devrait pas être considéré comme suffisant pour la cryptographie, etc." Cela devrait être fortement souligné.
Scott Arciszewski
4

La version modifiée de la fonction fonctionne très bien, mais j'ai trouvé un seul problème: vous avez utilisé le mauvais caractère pour entourer les caractères $, de sorte que le caractère 'fait parfois partie de la chaîne aléatoire qui est générée.

Pour résoudre ce problème, modifiez:

$characters = 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ’;

à:

$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

De cette façon, seuls les caractères inclus sont utilisés et le caractère 'ne fera jamais partie de la chaîne aléatoire générée.

bmcswee
la source
4

Un autre à une ligne, qui génère une chaîne aléatoire de 10 caractères avec des lettres et des chiffres. Il créera un tableau avec range(ajustez le deuxième paramètre pour définir la taille), boucle sur ce tableau et attribue un caractère ASCII aléatoire (plage 0-9 ou az), puis implose le tableau pour obtenir une chaîne.

$str = implode('', array_map(function () { return chr(rand(0, 1) ? rand(48, 57) : rand(97, 122)); }, range(0, 9)));

Remarque: cela ne fonctionne qu'en PHP 5.3 et versions ultérieures

Kasimir
la source
enfin une solution vraiment aléatoire pas un hachage gonflé d'un entier aléatoire de 32 bits ou une chaîne mélangée ...
The Surrican
Il n'y a qu'un seul problème: les nombres sont aussi susceptibles de se produire que les personnages, ce qui n'est pas aussi aléatoire que j'aimerais l'avoir. anyaway +1 pour la meilleure solution sur cette page. peaufiner cela et son parfait.
Le Surrican
peaufiner ... comme ça? rand(0, 57-48+122-97)<57-48?...:...? :)
vp_arth
4

Bon mot.

Il est rapide pour les énormes cordes avec un certain caractère unique.

function random_string($length){
    return substr(str_repeat(md5(rand()), ceil($length/32)), 0, $length);
}
Jacob Smith
la source
md5(rand())est un moyen horriblement peu sûr de générer un nombre aléatoire.
Scott Arciszewski
1
une chaîne avec une longueur X et une unicité est l'intention. le vrai hasard n'est pas l'intention.
Jacob Smith
3

J'ai aimé le dernier commentaire qui a utilisé openssl_random_pseudo_bytes, mais ce n'était pas une solution pour moi car je devais encore supprimer les caractères que je ne voulais pas, et je n'ai pas pu obtenir une chaîne de longueur définie. Voici ma solution ...

function rndStr($len = 20) {
    $rnd='';
    for($i=0;$i<$len;$i++) {
        do {
            $byte = openssl_random_pseudo_bytes(1);
            $asc = chr(base_convert(substr(bin2hex($byte),0,2),16,10));
        } while(!ctype_alnum($asc));
        $rnd .= $asc;
    }
    return $rnd;
}
RKaneKnight
la source
3
function randomString($length = 5) {
    return substr(str_shuffle(implode(array_merge(range('A','Z'), range('a','z'), range(0,9)))), 0, $length);
}
Anjith KP
la source
3

Voici ma solution simple en une ligne pour générer un mot de passe aléatoire convivial, excluant les caractères qui se ressemblent tels que "1" et "l", "O" et "0", etc ... ici, c'est 5 caractères mais vous pouvez facilement changez-le bien sûr:

$user_password = substr(str_shuffle('abcdefghjkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ23456789'),0,5);
rAthus
la source
C'est parfait pour créer des chaînes d'ID aléatoires à appeler plus tard sur jquery. IDK si c'est une bonne pratique mais cela m'a beaucoup aidé, sans utiliser un pour comme la réponse acceptée ...
Rodrigo Zuluaga
3

Voici une autre solution.

function genRandomString($length = 10)
{
    if($length < 1)
        $length = 1;
    return substr(preg_replace("/[^A-Za-z0-9]/", '', base64_encode(openssl_random_pseudo_bytes($length * 2))), 0, $length);
}

PS. J'utilise PHP 7.2 sur Ubuntu.

Umair Khan
la source
2

Une autre façon de générer une chaîne aléatoire en PHP est:

function RandomString($length) {
    $original_string = array_merge(range(0,9), range('a','z'), range('A', 'Z'));
    $original_string = implode("", $original_string);
    return substr(str_shuffle($original_string), 0, $length);
}
echo RandomString(6);
Akhilraj NS
la source
2

Voici comment je le fais pour obtenir une véritable clé aléatoire unique:

$Length = 10;
$RandomString = substr(str_shuffle(md5(time())), 0, $Length);
echo $RandomString;

Vous pouvez utiliser time () car il s'agit d'un horodatage Unix et est toujours unique par rapport aux autres aléatoires mentionnés ci-dessus. Vous pouvez ensuite générer la somme md5 de cela et prendre la longueur souhaitée dont vous avez besoin à partir du MD5 généré chaîne . Dans ce cas, j'utilise 10 caractères et je pourrais utiliser une chaîne plus longue si je veux la rendre plus unique.

J'espère que ça aide.

sherpa
la source
2
Bien sûr, time()est loin d'être unique: il retournera la même valeur encore et encore jusqu'à la fin de la seconde actuelle. Ce qui fournit vraiment un peu d'aléatoire ici, c'est que str_shuffle()le reste du code ne réduit que l'échantillon pour sélectionner les caractères.
Álvaro González
1
donc ce que vous faites essentiellement est de mélanger autour d'un entier 32 bits. pas beaucoup d'entropie ici ...
The Surrican
2
Un attaquant peut deviner la valeur retournée par time()(ce n'est qu'un horodatage), c'est une faible source d'aléatoire.
AL
2

One-liner paramétré utilisant uniquement des fonctions natives PHP , fonctionnant depuis PHP 5.1.0

str_shuffle(implode('', (array_intersect_key(($map =  array_map('chr', array_merge(array_map('mt_rand', array_fill(0, $length = 25, 48), array_fill(0,$length,57)),array_map('mt_rand', array_fill(0, $length, 65), array_fill(0,$length,90)),array_map('mt_rand', array_fill(0, $length, 97), array_fill(0,$length,122))))), array_flip($keys = array_rand($map, $length))))))
user10099
la source