Je n'ai pu trouver la réponse pour la raison nulle part, même la page wiki ne l'explique pas. Cela ressemble à utiliser un PRNG pour amorcer un autre PRNG. Le premier (/ dev/random) peut lui-même être ensemencé par un PRNG.
Je peux 'comprendre' pourquoi the-Rand
option ne peut pas être utilisée directement pour générer des clés, mais je ne vois pas la raison des sources principales. Beaucoup de gens disent/dev/random
ne produit pas suffisamment de sortie, ce qui est incorrect lorsque son entropie est alimentée par un démon.
Est-ce qu'ils considèrent/dev/random
ne pas être une source de qualité?
La lecture d'octets à partir d'un périphérique peut être gênante (vous devez tenir compte des spécificités de l'appel système, par exemple des appels système interrompus) et peut potentiellement être inefficace si vous lisez de nombreux petits morceaux (un syscall a une surcharge non négligeable). Un logiciel personnalisé PRNG, amorcé avec des octets de /dev/urandom
, donne plus de contrôle sur les performances.
(De plus, il peut y avoir un peu de syndrome NIH ici aussi.)
Si vous demandez pourquoi openssl Rand
ou Rand_bytes()
ne régurgitez pas simplement /dev/random
Ou /dev/urandom
, c'est parce que leur fonction est de servir uniquement de PRNG, et ils font exactement cela:
La commande
Rand
génère un nombre d'octets pseudo-aléatoires après avoir initialisé une fois le générateur de nombres aléatoires.
Un OpenSSL correctement compilé et opérationnel lira 32 octets de /dev/urandom
Là où il est disponible (et à moins qu'un moteur matériel soit spécifié à la place), et utilisera (une partie ou la totalité de) ceci pour amorcer un PRNG. Vous pouvez confirmer si random
ou urandom
sont lus avec strace
sur un système * nix avec:
$ strace -xe trace=file,read,write,close openssl Rand 10
[...]
open("/dev/urandom", O_RDONLY|O_NOCTTY|O_NONBLOCK) = 3
read(3, "\x26\x20\xfc\x61\x59\x81\xc9\x4d\xe5\x27\xab\xc2\x72\xb1"..., 32) = 32
close(3) = 0
Quant à pourquoi il en est ainsi, en tant que bibliothèque de logiciels, OpenSSL ne peut pas générer directement des nombres vraiment aléatoires . Les choix sont d'utiliser un PRNG cryptographiquement sécurisé avec une bonne graine aléatoire (c'est-à-dire avec des données OS récoltées à partir d'événements matériels effectivement aléatoires); ou utilisez un vrai RNG matériel. La section Hardware du wiki explique comment faire ce dernier, y compris comment accéder au RNG sur puce (RDRAND d'Intel) en utilisant la fonction "moteur". L'excellente réponse de Thomas Pornin explique ici pourquoi un (correctement semé, cryptographiquement sécurisé) PRNG est suffisant pour la plupart des applications: Évaluation de la collecte d'entropie dans un PRNG
Si vous voulez être en charge de fournir des données aléatoires à OpenSSL de manière configurable, l'utilisation d'une socket style EGD peut être l'option la plus simple. Si vous souhaitez alimenter des nombres aléatoires directement via l'API OpenSSL, un moteur est la "meilleure" option (bien que vous puissiez tricher un pe , exemple ici )
Je pense qu'OpenSSL utilise son propre algorithme PRNG , sauf si vous avez FIPS activé.
OpenSSL utilise absolument quand il est disponible /dev/random
: Un extrait de ne des réponses dans le FAQ :
Toutes les versions d'OpenSSL essaient d'utiliser/dev/urandom par défaut; à partir de la version 0.9.7, OpenSSL essaie également/dev/random si/dev/urandom n'est pas disponible.
et la page wiki à laquelle vous faites référence:
Initialisation
OpenSSL tentera d'amorcer automatiquement le générateur de nombres aléatoires lors de l'instanciation en appelant Rand_poll. Rand_poll amorce le générateur de nombres aléatoires à l'aide d'une source d'entropie spécifique au système, qui est/dev/urandom sur les systèmes d'exploitation de type UNIX, et est une combinaison de CryptGenRandom et d'autres sources d'entropie sur Windows.
Vous avez également demandé s'il s'agissait "d'amorcer un PRNG à partir d'un PRNG", cela dépend de la façon dont vous définissez strictement un PRNG. Une propriété qui définit un PRNG est qu'il est déterministe , un PRNG a un point de départ "secret" (défini par la graine ), ensuite il est prévisible (si vous connaissez ce secret et le courant itération ou, par extension, l'état interne). Alors qu'un Linux random
normal n'est clairement pas un vrai RNG "inobservable" ou quantique, ce n'est pas non plus un PRNG tout à fait normal puisque sa sortie diverge assez rapidement des valeurs déterministes que l'amorçage initial entraînerait dans. Conjecture de côté, je pense que le terme contemporain est un " PRNG avec entrée ", voir ceci papier PDF , donc un qualifié "oui".
Depuis 0.9.7, OpenSSL utilise par défaut (DEVRANDOM
define) pour utiliser dans l'ordre: /dev/urandom
, /dev/random
, /dev/srandom
(Avec des lectures non bloquantes de 10 ms) et conseille :
/* Use a random entropy pool device. Linux, FreeBSD and OpenBSD * have this. Use /dev/urandom if you can as /dev/random may block * if it runs out of random entries. */
(OpenSSL-1.0.1e crypt/Rand/rand_unix.c
)
Le contenu de "random
" doit être utilisé avec parcimonie car il est livré avec une certaine qualité implicite et est limité en taux. Bien que urandom
ne se bloque pas, cela implique que sa qualité se dégrade avec l'utilisation. (Au moins sous Linux, urandom
est différent sur les autres plates-formes.)
Enfin, une histoire ancienne ... OpenSSL est dérivé de SSLeay (OpenSSL est né à v0.9.0), et SSLeay (0.1 publié en avril 1995) pré -date les RNG (P) gérés par le système d'exploitation couramment disponibles. Linux a été le premier à avoir un périphérique random
dans v1.3. en 1994, suivi de FreeBSD 2.2 en 1995. Le Rand_bytes()
PRNG date de cette époque, il est donc intéressant de voir dans la documentation (doc/Rand.doc
de 0.5.1b):
First up I will state the things I believe I need for a good RNG. 1) A good hashing algorithm to mix things up and to convert the RNG 'state' to random numbers. 2) An initial source of random 'state'. 3) The state should be very large. [...snip...]
qui est suivie d'une discussion plus approfondie et d'un résumé clair:
So of the points raised, only 2 is not addressed, but sources of random data will always be a problem.
SSLeay a d'abord pris en charge /dev/random
Dans la version 0.5.3 (probablement début 1996, les journaux de modifications sont un peu vagues). Avant cela, le PID, l'UID, l'horodatage et l'AFAICT, tout ce qui était sur la pile devait suffire. Donc, Rand_bytes()
a toujours été un PRNG parce que c'est une solution rapide et portable. Il utilise tout ce qu'il peut récupérer pour amorcer le PRNG pour donner une quantité utile de données aléatoires, y compris le caractère aléatoire fourni par le système d'exploitation. Lorsqu'il existe une alternative matérielle spécifique à un PRNG, un moteur de chiffrement peut fournir cette fonctionnalité.
En ce qui concerne le comportement de -Rand
Je suppose que vous voulez dire lorsqu'il est utilisé avec quelque chose comme "openssl genrsa 2028
". Il se comporte probablement de cette façon, car une quantité modérée mais indéterminée de données aléatoires est requise (des nombres sont générés au hasard et testés pour la primauté, une paire est nécessaire) et l'alternative n'a jamais été considérée comme utile (environ 10 à 40 kio de données vraiment aléatoires , comme une supposition éclairée).
En général, les raisons de ne pas utiliser directement la source aléatoire telles que présentées comprennent:
/dev/urandom
en particulier n'est pas fiable car en garantissant qu'il ne se bloquera pas dans des conditions de faible entropie, il ne garantit pas que la sortie est réellement aléatoire. La page de manuel man 4 urandom
contient plus d'informations à ce sujet, y compris une allusion énigmatique à une attaque qu'un organisme gouvernemental peut ou non avoir fondée sur cette condition. Des tests d'adéquation peuvent être effectués sur ces données, ou ils peuvent être mutés d'une manière ou d'une autre pour concentrer l'entropie, ou différentes sources peuvent être combinées.Considérez également le concept de taille de clé effective (le logarithme en base 2 du nombre d'itérations d'un algorithme optimal pour briser la clé étant donné un élément connu chiffré avec elle). Il est évidemment inutile de consommer plus de bits d'entropie que la taille de clé effective, et cela ne fait qu'épuiser le pool d'entropie.
En plus de l'excellente réponse de Falcon:
[colin@localhost ~]$ time dd if=/dev/random of=/dev/null iflag=fullblock count=10 bs=32
10+0 records in
10+0 records out
320 bytes (320 B) copied, 32.0067 s, 0.0 kB/s
0.00user 0.00system 0:32.00elapsed 0%CPU (0avgtext+0avgdata 3104maxresident)k
0inputs+0outputs (0major+249minor)pagefaults 0swaps
[colin@localhost ~]$ time dd if=/dev/urandom of=/dev/null iflag=fullblock count=10 bs=32
10+0 records in
10+0 records out
320 bytes (320 B) copied, 0.000289421 s, 1.1 MB/s
0.00user 0.00system 0:00.00elapsed 0%CPU (0avgtext+0avgdata 3072maxresident)k
0inputs+0outputs (0major+247minor)pagefaults 0swaps
/ dev/random peut être très aléatoire, mais c'est très, très lent!