Outils pour utilisateurs

Outils du site


web:php:random

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);
web/php/random.1361896804.txt.gz · Dernière modification : le 26/02/2013 à 16:40 de Yosko