web-dev-qa-db-fra.com

Pourquoi OpenSSL ne peut pas utiliser / dev / random directement?

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-Randoption 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/randomne pas être une source de qualité?

22
user2284570

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.)

19
Thomas Pornin

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).

13
mr.spuratic

En général, les raisons de ne pas utiliser directement la source aléatoire telles que présentées comprennent:

  • Vous n'avez peut-être pas besoin d'autant de bits d'entropie que vous en avez besoin. Dans ce cas, vous pouvez utiliser les bits aléatoires pour amorcer un générateur de nombres pseudo-aléatoires. Ceci est plus important lorsque l'entropie est rare (cette contrainte devient moins pertinente au fil du temps à mesure que les sources d'entropie matérielles dédiées deviennent plus courantes).
  • Vous ne voulez pas croire que la source aléatoire est aléatoire. /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.
  • Vous souhaitez garantir qu'une méthode particulière de génération de nombres aléatoires a été utilisée. Cela vous permet de vous conformer à toute norme exigeant cela sans avoir à compter sur les développeurs du noyau Linux pour le faire pour vous.

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.

2
Falcon Momot

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!

1
symcbean