Voici quelques réflexions. Si vous êtes impatient, passez directement à la conclusion, à la fin.
1. Qu'est-ce qu'une graine sécurisée ?
La sécurité n'est définie que par rapport à un modèle d'attaque. Nous voulons ici une séquence de n bits, qui a n d'entropie par rapport à l'attaquant : en d'autres termes, que n'importe lequel des possibles 2 n pour cette séquence sont également probables du point de vue de l'attaquant.
Il s'agit d'un modèle qui se rapporte à la information à la disposition de l'attaquant. L'application qui génère et utilise la graine (normalement dans un PRNG) connaît la graine exacte ; le fait que la graine soit "sûre" n'est pas une propriété absolue de la graine ou même du processus de génération de la graine. Ce qui importe, c'est la quantité d'informations dont dispose l'attaquant sur le processus de génération. Ce niveau d'information varie largement en fonction de la situation ; par exemple, sur un système multi-utilisateurs (disons de type Unix, avec une séparation des applications renforcée par le matériel), la synchronisation précise des accès à la mémoire peut révéler des informations sur la façon dont un processus nominalement protégé lit la mémoire. Même un attaquant distant peut obtenir de telles informations ; ceci a été a démontré (dans des conditions de laboratoire) sur le cryptage AES (les implémentations AES typiques utilisent des tables internes, avec des schémas d'accès qui dépendent de la clé ; l'attaquant force les manques de cache et les détecte grâce à un timing précis des réponses du serveur).
La durée de vie de la graine doit être prise en compte. La graine est sûre tant qu'elle reste inconnue de l'attaquant ; cette propriété doit rester vraie par la suite. En particulier, il ne doit pas être possible de récupérer la graine à partir d'extraits de la sortie ultérieure du PRNG. Idéalement, même l'obtention de l'état complet du PRNG à un moment donné ne devrait donner aucun indice sur les bits que le PRNG a produits auparavant.
Ce que je veux dire ici, c'est qu'une graine n'est "sûre" que si elle est utilisée dans un contexte où elle peut rester sûre, ce qui implique plus ou moins un PRNG cryptographiquement sûr et un stockage inviolable. Si un tel stockage est disponible, la graine la plus sûre est celle qui a été générée. une fois il y a longtemps, et utilisé dans un PRNG sécurisé hébergé par du matériel inviolable.
Malheureusement, un tel matériel est coûteux (il s'appelle un HSM et coûte quelques centaines ou milliers de dollars), et ce coût s'avère généralement difficile à justifier (une mauvaise graine n'empêchera pas un système de fonctionner ; c'est le problème habituel de la non-testabilité de la sécurité). C'est pourquoi il est d'usage d'opter pour des solutions "essentiellement logicielles". Puisque les logiciels ne sont pas aptes à fournir un stockage confidentiel à long terme, la durée de vie de la graine est arbitrairement réduite : une nouvelle graine est obtenue périodiquement. Dans Fortuna Ce réensemencement est censé se produire au moins une fois par mégaoctet de données pseudo-aléatoires générées.
En résumé, dans une configuration sans HSM, une graine sûre est une graine qui peut être obtenue relativement facilement (puisque nous le ferons assez souvent) en utilisant des données qui ne peuvent pas être recueillies par l'attaquant.
2. Mélange
Les sources de données aléatoires ne produisent pas de beaux bits uniformes (chaque bit ayant la valeur 1 avec une probabilité exacte de 1). 0.5 et les valeurs des bits sont indépendantes les unes des autres). Au lieu de cela, les sources aléatoires produisent des valeurs dans un ensemble spécifique à la source. Ces valeurs peuvent être codées sous forme de séquences de bits, mais on n'en a pas pour son argent : pour avoir n bits d'entropie, vous devez avoir des valeurs qui, lorsqu'elles sont encodées, utilisent beaucoup plus que les bits d'entropie. n bits.
L'outil cryptographique à utiliser ici est un PRF qui accepte une entrée d'une longueur arbitraire et produit un fichier n -bit de sortie. Une PRF cryptographiquement sécurisée de ce type est modélisée comme une oracle aléatoire En bref, il n'est pas possible, d'un point de vue informatique, de prédire quoi que ce soit sur la sortie de l'oracle pour une entrée donnée sans l'essayer.
En ce moment, nous avons fonctions de hachage . Les fonctions de hachage doivent remplir quelques propriétés de sécurité, à savoir la résistance aux préimages, aux secondes préimages et aux collisions. Nous analysons généralement les fonctions de hachage en essayant de voir comment elles s'écartent du modèle de l'oracle aléatoire. Il y a un point important ici : une PRF qui suit le modèle de l'oracle aléatoire sera une bonne fonction de hachage, mais il peut y avoir de bonnes fonctions de hachage (dans le sens de la résistance aux préimages et aux collisions) qui sont néanmoins faciles à distinguer d'un oracle aléatoire. En particulier, le SHA-2 (SHA-256, SHA-512...) sont considérées comme sûres, mais s'écartent du modèle de l'oracle aléatoire en raison de l'"attaque par extension de longueur" (étant donné h(m) il est possible de calculer h(m || m') pour un message partiellement contraint m' sans savoir m ). L'attaque par extension de longueur ne semble pas fournir de raccourci pour la création de pré-images ou de collisions, mais elle montre que ces fonctions de hachage ne sont pas des oracles aléatoires. Pour le Concours SHA-3 Le NIST a déclaré que les candidats ne devaient pas autoriser une telle "extension de la longueur".
L'étape du mélange n'est donc pas facile. Votre meilleure chance est encore, pour l'instant, d'utiliser SHA-256 ou SHA-512, et de passer à SHA-3 lorsqu'il sera choisi (cela devrait arriver vers la mi-2012).
3. Sources
Un ordinateur est une machine déterministe. Pour obtenir une part d'aléatoire, il faut y mêler le résultat de certaines mesures du monde physique.
Une note philosophique : à un moment donné, il faut faire confiance à des personnes intelligentes, celles qui portent des blouses de laboratoire ou qui sont payées pour faire de la recherche fondamentale. Lorsque vous utilisez une fonction de hachage telle que SHA-256, vous faites en fait confiance à un groupe de cryptographes lorsqu'ils vous disent : nous avons cherché des failles, très fort, et pendant plusieurs années, et n'en avons trouvé aucune. Lorsque vous utilisez un morceau de matière radioactive en décomposition avec un compteur Geiger, vous faites confiance à des physiciens qui vous disent : nous avons cherché très fort des moyens de prédire quand le prochain noyau atomique explosera, mais nous n'en avons trouvé aucun. Notez que, dans ce cas précis, les "physiciens" sont des gens comme Becquerel, Rutherford, Bohr ou Einstein, et que "vraiment difficile" signifie "plus d'un siècle de recherche accumulée", donc vous n'êtes pas exactement en territoire inconnu. Pourtant, il y a encore un peu de foi dans la sécurité.
Certains ordinateurs comprennent déjà du matériel qui génère des données aléatoires (c'est-à-dire qui utilise et mesure un processus physique qui, d'après les physiciens, est suffisamment aléatoire). Le VIA C3 (une ligne de CPU compatibles x86) possède un tel matériel. Étrangement, le Commodore 64, ordinateur familial d'il y a 30 ans, disposait également d'un RNG matériel (c'est du moins ce qu'on dit). Wikipedia au moins).
Sauf matériel spécial, vous devez utiliser tous les événements physiques que vous pouvez obtenir. Typiquement, vous utiliserez les frappes au clavier, les paquets Ethernet entrants, les mouvements de souris, les accès au disque dur... chaque événement est accompagné de données et se produit à un instant mesurable (les processeurs modernes ont des horloges très précises, grâce aux compteurs de cycles). Ces instants, et le contenu des données de l'événement, peuvent être accumulés comme des sources d'entropie. Ceci est beaucoup plus facile pour le système d'exploitation lui-même (qui a un accès direct au matériel) que pour les applications, donc la façon normale de collecter une graine est de demander au système d'exploitation (sous Linux, cela s'appelle /dev/random
ou /dev/urandom
(les deux ont des avantages et des problèmes, choisissez votre poison) ; sous Windows, appelez CryptGenRandom()
).
Un cas extrême est celui des applets Java d'avant la version 1.2, avant l'ajout de la fonction java.security.SecureRandom
; comme Java est très efficace pour isoler le code d'application du matériel, obtenir une graine aléatoire était un défi difficile à relever. La solution habituelle était d'avoir deux ou trois threads fonctionnant simultanément et changeant follement de thread, de sorte que le nombre de changements de threads par seconde soit quelque peu aléatoire (en fait, cela tente d'extraire le caractère aléatoire à travers le timing des actions du planificateur du système d'exploitation, qui dépendent de ce qui se passe également sur la machine, y compris les événements liés au matériel). Ce n'était pas du tout satisfaisant.
Un problème avec les mesures liées au temps est que l'attaquant sait également quelle est l'heure actuelle. Si l'attaquant a un accès applicatif à la machine, il peut également lire le compteur de cycles.
Certaines personnes ont proposé d'utiliser les cartes audio comme sources de "bruit blanc" en réglant l'amplificateur à son maximum (même les serveurs ont de l'audio de nos jours). D'autres plaident pour la mise sous tension des webcams (nous savons que les vidéos des webcams sont "bruyantes" et que c'est bon pour le hasard, même si la webcam est face à un mur) ; mais les serveurs avec webcams ne sont pas courants. Vous pouvez également envoyer un ping à un serveur de réseau externe (par ex. www.google.com
) et voir combien de temps il met à revenir (mais cela pourrait être observé par un attaquant espionnant le réseau).
La beauté de l'étape de mélange, avec une fonction de hachage, est que l'entropie ne peut que s'accumuler ; il n'y a aucun mal à ajouter des données, même si ces données ne sont pas si aléatoires. Il suffit de faire passer autant de données que possible par la fonction de hachage. Les fonctions de hachage sont assez rapides (une bonne implémentation de SHA-512 traitera plus de 150 Mo/s sur un PC typique, en utilisant un seul cœur) et l'ensemencement ne se produit pas si souvent.
4. Conclusion
Utilisez un HSM . Ils coûtent quelques centaines ou milliers de dollars, mais vos secrets ne valent-ils pas beaucoup plus que cela ? Un HSM comprend du matériel RNG, exécute l'algorithme PRNG et stocke la graine avec une résistance à la falsification. En outre, la plupart des HSM sont déjà certifiés au regard de diverses réglementations nationales (par exemple, FIPS 140 aux États-Unis et les niveaux EAL en Europe).
Si vous êtes si bon marché que vous n'achèterez pas de HSM, ou si vous voulez protéger des données qui n'ont pas beaucoup de valeur, construisez un PRNG cryptographiquement sûr en utilisant une graine obtenue par hachage. lots de mesures physiques. Tout ce qui provient d'un matériel doit être haché, ainsi que l'instant (lire "compteur de cycles") auquel ces données ont été obtenues. Vous devriez hacher les données par mégaoctet ici. Ou, mieux encore, faites pas le faire : il suffit d'utiliser les facilités offertes par votre système d'exploitation, qui inclut déjà un tel code.