7.1.2. The /dev/random Device (Le périphérique /dev/random)
7.1.2. The /dev/random Device (Le périphérique /dev/random)
Plusieurs versions du système d'exploitation UNIX fournissent un générateur de nombres aléatoires résident dans le noyau. Certains de ces générateurs utilisent des événements capturés par le noyau pendant le fonctionnement normal du système.
Par exemple, sur certaines versions de Linux, le générateur consiste en un réservoir aléatoire de 512 octets représenté comme 128 mots de 4 octets chacun. Lorsqu'un événement se produit, tel qu'une interruption de lecteur de disque, le temps de l'événement est XORé dans le réservoir, et le réservoir est remué via un polynôme primitif de degré 128. Le réservoir lui-même est traité comme un tampon circulaire, avec de nouvelles données étant XORées (après remuage avec le polynôme) sur l'ensemble du réservoir.
Chaque appel qui ajoute de l'entropie au réservoir estime la quantité d'entropie vraie probable que l'entrée contient. Le réservoir lui-même contient un accumulateur qui estime l'entropie totale du réservoir.
Les événements d'entrée proviennent de plusieurs sources, comme énuméré ci-dessous. Malheureusement, pour les machines serveur sans opérateurs humains, les première et troisième ne sont pas disponibles, et l'entropie peut être ajoutée lentement dans ce cas.
-
Interruptions de clavier. Le temps de l'interruption et le code de scan sont ajoutés au réservoir. Cela ajoute en effet de l'entropie de l'opérateur humain en mesurant les temps d'arrivée inter-frappes.
-
Achèvement de disque et autres interruptions. Un système utilisé par une personne aura probablement un modèle difficile à prédire d'accès disque. (Mais tous les pilotes de disque ne supportent pas la capture de ces informations de timing avec une précision suffisante pour être utiles.)
-
Mouvement de souris. Le timing et la position de la souris sont ajoutés.
Lorsque des octets aléatoires sont requis, le réservoir est haché avec SHA-1 [SHA*] pour produire les octets d'aléa retournés. Si plus d'octets sont requis que la sortie de SHA-1 (20 octets), alors la sortie hachée est remuée dans le réservoir et un nouveau hachage est effectué pour obtenir les 20 octets suivants. Au fur et à mesure que les octets sont retirés du réservoir, l'estimation de l'entropie est décrémentée en conséquence.
Pour assurer un réservoir raisonnablement aléatoire au démarrage du système, les scripts de démarrage et d'arrêt standards sauvegardent le réservoir dans un fichier disque lors de l'arrêt et lisent ce fichier au démarrage du système.
Il existe deux interfaces exportées à l'utilisateur. /dev/random retourne des octets du réservoir mais bloque lorsque l'entropie estimée tombe à zéro. Au fur et à mesure que l'entropie est ajoutée au réservoir à partir d'événements, plus de données deviennent disponibles via /dev/random. Les données aléatoires obtenues d'un tel périphérique /dev/random conviennent à la génération de clés pour des clés à long terme, si suffisamment de bits aléatoires sont dans le réservoir ou sont ajoutés dans un délai raisonnable.
/dev/urandom fonctionne comme /dev/random; cependant, il fournit des données même lorsque l'estimation d'entropie pour le réservoir aléatoire tombe à zéro. Cela peut être adéquat pour les clés de session ou pour d'autres tâches de génération de clés pour lesquelles le blocage en attente de plus de bits aléatoires n'est pas acceptable. Le risque de continuer à prendre des données même lorsque l'estimation d'entropie du réservoir est petite est que la sortie passée peut être calculable à partir de la sortie actuelle, à condition qu'un attaquant puisse inverser SHA-1. Étant donné que SHA-1 est conçu pour être non inversible, c'est un risque raisonnable.
Pour obtenir des nombres aléatoires sous Linux, Solaris ou d'autres systèmes UNIX équipés du code décrit ci-dessus, tout ce qu'une application doit faire est d'ouvrir soit /dev/random soit /dev/urandom et de lire le nombre désiré d'octets.
(Le périphérique Linux Random a été écrit par Theodore Ts'o. Il était basé approximativement sur le générateur de nombres aléatoires dans PGP 2.X et PGP 3.0 (alias PGP 5.0).)