Ceci est une ancienne révision du document !
Table des matières
Nombres aléatoires en PHP
Note : article en cours de rédation
Crypto
L'utilisation de fonctions telles que rand()
ou mt_rand()
n'est pas considéré comme sécurisé pour une utilisation en cryptographie. S'il existe des fonctions préférables, elles sont généralement inclues dans des modules non installés par défaut.
Sous Linux/Unix, une solution consiste à aller lire le fichier /dev/random, qui génère des nombres aléatoires. On peut indiquer le nombre d'octets qu'on souhaite lire :
$nbBytes = 1; $random = file_get_contents('/dev/random', false, null, 0, $nbBytes);
Cet exemple retournera 1 octet aléatoires. Pour rappel, 1 octet = 8 bits.
Ces caractères seront illisibles. Si l'on souhaite les convertir en chaine, le plus simple peut être de les convertir en base64 (caractères de 6 bits : 26 = 64).
$base64 = base64_encode($random); echo $base64;
L'exemple ci-dessus affichera par exemple Mg==
.
On a en entrée un multiple de 8 bits, et en sortie un multiple de 6. Leur plus petit commun multiple (PPCM) est 24 (24 bits = 3 octets ou 4 caractères en base64).
Du coup, pour chaque groupon de 3 octets en entrée, on se retrouvera avec 4 caractères en sortie. Mais si on ne fourni pas un multiple de 3, comme dans notre exemple, on obtiendra tout de même 24 bits en sortie.
Ainsi, avec un octet :
//octet en entrée : 8 bits, où X peut valoir 0 ou 1 XXXXXXXX //on complète pour avoir un multiple de 6 bits XXXXXXXX0000 //on découpe en caractères de 6 bits XXXXXXXX0000 \____/\____/ M g //on complète pour retourner 4 caractères XXXXXXXX0000++++++++++++ \____/\____/\____/\____/ M g = =
Si j'ai distingué ci-dessus le 0
du +
, c'est parce que =
qu'on a en sorti n'existe par réellement dans la table des caractères en base64.
De fait, dans notre exemple, le second caractère ne pourra avoir que 4 valeurs différentes : A (000000), Q (010000), g (100000) ou w (110000). Il n'est donc pas aussi aléatoire que le premier.
En résumé, où N est un multiple de 3 :
- si le nombre d'octets fournis en entrée de
base64()
est N, tous les caractères retournés seront réellement aléatoires. - Si il est N+1, il y aura un caractère un peu moins aléatoire suivi de 2
=
. Il faut donc se débarrasser des 3 derniers caractères. - Si il est N+2, il y aura un caractère un peu moins aléatoire suivi de 1
=
. Il faut donc se débarrasser des 2 derniers caractères.
Seulement sous Linux/Unix (/dev/urandom). A n'utiliser que ponctuellement (génération d'ID de session, de sel pour hashage de mot de passe, etc…).
//31 binary characters from urandom will result in a 42 long base64 encoded string $nbBytes = 31; //read random bytes from /dev/urandom $random = file_get_contents('/dev/urandom', false, null, 0, $nbBytes); //turn binary string to readable string //(base64 is [a-zA-Z0-9] with also '+' and '/', with padding '=') $base64 = base64_encode($random); $base64 = str_replace('=', '', $base64); //optionally: turn the string into a usable string in //scripts that dislike the '+' like Blowfish $base64 = str_replace('+', '.', $base64);