Das Lesen von / dev / random erzeugt keine Daten

19

Ich benutze oft den Befehl

cat /dev/urandom | strings --bytes 1 | tr -d '\n\t ' | head --bytes 32

um pseudozufällige Passwörter zu generieren. Das geht nicht mit /dev/random.

Speziell

  • cat /dev/urandom | strings --bytes 1 | tr -d '\n\t ' Erzeugt eine Ausgabe
  • cat /dev/random | strings --bytes 1 Erzeugt eine Ausgabe
  • cat /dev/random | strings --bytes 1 | tr -d '\n\t ' erzeugt keine Ausgabe

NB: Bei der Verwendung müssen /dev/randomSie möglicherweise mit der Maus wackeln oder Tasten (z. B. Strg, Umschalttaste usw.) drücken, um Entropie zu erzeugen.

Warum funktioniert das letzte Beispiel nicht? Hat tres einen großen internen Puffer, der /dev/urandomsich schnell füllt, aber /dev/randomnicht?

PS Ich benutze CentOS 6.5

cat /proc/version
Linux version 2.6.32-431.3.1.el6.x86_64 ([email protected]) (gcc version 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC) ) #1 SMP Fri Jan 3 21:39:27 UTC 2014
Aaron J Lang
quelle
Was ist Ihre Distribution, Ihre Kernel-Version? Auf Cygwin geben beide Werte zurück.
Kiwy
@ Kiwy Siehe bearbeiten.
Aaron J Lang
1
Sie wissen pwgen, insbesondere pwgen -s?
MvG
2
Der -sSchalter macht sie weniger einprägsam, eher zufällig. @Boyd: Ist makepasswd weit über die Debian-basierten Distributionen hinaus verfügbar? So wie ich es sehe, ist pwgen für CentOS während makepasswd nicht .
MvG
1
@BoydStephenSmithJr. Ich stimme @ MvG zu, makepasswddas auf meiner Plattform sowieso nicht verfügbar ist
Aaron J Lang

Antworten:

27

Es wird irgendwann.

Im:

cat /dev/random | strings --bytes 1 | tr -d '\n\t '

cat wird nie puffern, aber es ist sowieso überflüssig, da es hier nichts zu verketten gibt.

< /dev/random strings --bytes 1 | tr -d '\n\t '

stringsDa seine Ausgabe jedoch nicht länger ist, puffert ein Terminal seine Ausgabe in Blöcken (von etwa 4 oder 8 kB) im Gegensatz zu Zeilen, wenn die Ausgabe an ein Terminal geht.

Es beginnt also erst dann mit dem Schreiben auf stdout, wenn es Zeichen im Wert von 4 KB für die Ausgabe gesammelt hat, was /dev/randomeinige Zeit in Anspruch nehmen wird.

trDie Ausgabe wird an ein Terminal gesendet (wenn Sie dies an einer Shell-Eingabeaufforderung in einem Terminal ausführen), sodass die Ausgabe zeilenweise gepuffert wird. Da Sie das entfernen \n, muss nie eine vollständige Zeile geschrieben werden, sondern es wird geschrieben, sobald ein vollständiger Block akkumuliert wurde (z. B. wenn die Ausgabe nicht an ein Terminal geht).

Es trist also wahrscheinlich, dass nichts geschrieben wird, bis stringsgenug /dev/randomDaten gelesen wurden , um 8 KB (2 Blöcke, möglicherweise viel mehr) Daten zu schreiben (da der erste Block wahrscheinlich einige Zeilenumbrüche, Tabulatoren oder Leerzeichen enthält).

Auf diesem System, das ich /dev/randomanprobiere , kann ich durchschnittlich 3 Bytes pro Sekunde ab (im Gegensatz zu 12MiB ab /dev/urandom), also im besten Fall (die ersten 4096 Bytes von /dev/randomsind alle druckbar) 22 Minuten vorher trzu sprechen beginnt, etwas auszugeben. Aber es wird mit größerer Wahrscheinlichkeit Stunden dauern (in einem kurzen Test kann ich feststellen strings, dass alle 1 bis 2 gelesenen Blöcke ein Block geschrieben wird und die Ausgabeblöcke etwa 30% der Zeilenumbruchzeichen enthalten, daher würde ich erwarten, dass sie gelesen werden müssen Mindestens 3 Blöcke davor müssen tr4096 Zeichen ausgegeben werden.

Um dies zu vermeiden, können Sie Folgendes tun:

< /dev/random stdbuf -o0 strings --bytes 1 | stdbuf -o0 tr -d '\n\t '

stdbuf ist ein GNU-Befehl (auch in einigen BSDs enthalten), der die stdio-Pufferung von Befehlen über einen LD_PRELOAD-Trick ändert.

Beachten Sie, dass Sie stattdessen verwenden stringskönnen, tr -cd '[:graph:]'wodurch auch Tabulator, Zeilenumbruch und Leerzeichen ausgeschlossen werden.

Möglicherweise möchten Sie auch das Gebietsschema korrigieren, Cum mögliche zukünftige Überraschungen mit UTF-8-Zeichen zu vermeiden.

Stéphane Chazelas
quelle
Wow beeindruckende Erklärung.
Kiwy
2
Tolle! Tolle Erklärung und Lösung. Ich habe immer cat"nutzlos" verwendet, weil ich es nie gemocht habe, stdin am Ende einer Pipeline umzuleiten. Jetzt kann ich einen Prozess "speichern" und habe immer noch lesbare Befehle. Meine endgültige Lösung war< /dev/random stdbuf -o0 tr -Cd '[:graph:]' | stdbuf -o0 head --bytes 32
Aaron J Lang
@ AaronJLang, guter Punkt über [:graph:]. Ich hatte das vergessen.
Stéphane Chazelas
@AaronJLang, Sie brauchen das stdbuffor head -c32nicht, es sei denn, Sie möchten zulassen, dass es die Daten schreibt, sobald sie vorliegen (wie in mehreren Blöcken anstelle eines 32-Byte-Blocks, sobald sie vorliegen)
Stéphane Chazelas
2
Meiner Meinung nach ist / dev / urandom für die Verwendung durch den Autor ausreichend. Wenn jemand neugierig wäre, wie Urandom im Vergleich zu Random funktioniert, würde ich empfehlen, die Kommentare oben im Treiber in drivers / char / random.c des Kernel-Quellbaums zu lesen. Die Kommentare erwähnen eine Analyse des PRNG und seiner Implementierung. Hoffentlich wird in diesem Artikel die Frage beantwortet, wie zufällig mehr oder weniger Zufall im Vergleich zu Zufall ist. Verfügbar hier: eprint.iacr.org/2012/251.pdf
etherfish
5

Das Generieren von Zufallszahlen für viele Sicherheitsanwendungen erfordert ausreichende Entropie - Entropiemessungen, wie unvorhersehbar die Zufälligkeit ist. Ein deterministischer Prozessor kann keine Entropie erzeugen, daher muss die Entropie von außen kommen - entweder von einer Hardwarekomponente mit nicht deterministischem Verhalten oder von anderen Faktoren, die nur schwer reproduzierbar sind, z kommt herein). Sobald eine ausreichende Entropie verfügbar ist, kann Kryptographie verwendet werden, um einen praktisch unbegrenzten Strom von Zufallszahlen zu erzeugen.

Linux arbeitet, indem es Entropie in einem Pool ansammelt und dann mithilfe von Kryptografie akzeptable Zufallszahlen sowohl durch /dev/randomals auch erzeugt /dev/urandom. Der Unterschied besteht darin, dass /dev/randomeine äußerst konservative Entropieberechnung angewendet wird, die die Schätzung der Entropie im Pool für jedes von ihr erzeugte Byte verringert, während sie /dev/urandomsich nicht mit der Menge der Entropie im Pool befasst.

Wenn die Schätzung der Entropie im Pool zu niedrig ist, wird /dev/randomblockiert, bis mehr Entropie akkumuliert werden kann. Dies kann die Rate, mit der /dev/randomdie Ausgabe erfolgen kann, erheblich verkrüppeln . Dies ist, was Sie hier beobachten. Es hat nichts damit zu tun tr; stringsLiest aber die Ausgabe mit Pufferung, so muss ein voller Puffer (ein paar KB) /dev/randomnur gelesen werden , um mindestens ein Byte der Eingabe zu erzeugen.

/dev/urandomist für die Erzeugung eines kryptografischen Schlüssels vollkommen akzeptabel , da die Entropie in der Tat in keiner Weise wahrnehmbar abnimmt. (Wenn Sie Ihren Computer länger laufen lassen, als es das Universum gibt, können Sie diese Überlegungen nicht vernachlässigen, aber ansonsten sind Sie gut.) Es gibt nur einen Fall, in dem /dev/urandomnicht gut ist, nämlich auf einem frisch installierten System, auf dem es keine gibt Sie hatten noch keine Zeit, Entropie zu generieren, oder ein frisch gestartetes System, das von schreibgeschützten Medien gestartet wird.

Das Entfernen stringsvon Ihrer Boot-Kette wird Ihren Prozess wahrscheinlich beschleunigen. Im Folgenden trwerden nicht druckbare Zeichen gefiltert:

</dev/random LC_ALL=C tr -dc '!-~'

Aber Sie verwenden können , /dev/urandomhier , solange Sie darauf achten , keine Passwörter auf einem System zu erzeugen , die keine Zeit gehabt hat , um eine ausreichende Entropie zu akkumulieren. Sie können die Ebene des Linux-Entropiepools in überprüfen /proc/sys/kernel/random/entropy_avail(wenn Sie verwenden /dev/random, wird die Abbildung in dieser Datei konservativ sein, möglicherweise sehr).

Gilles 'SO - hör auf böse zu sein'
quelle
1

Verwenden Sie diese Option /dev/urandom, um qualitativ hochwertige (Pseudo-) Zufallszahlen zu erhalten, und zwar /dev/randomnur dann, wenn Sie absolut unvorhersehbare Zufallszahlen benötigen. Ein Angreifer unter den Ressourcen der NSA wird es sehr schwer haben zu knacken /dev/urandom(und die Gummischlauch-Kryptographie nicht vergessen ). Der Kernel füllt einen Puffer mit "wirklich zufälligen" Bytes, das /dev/randomgibt es. Leider ist die Rate , mit der diejenigen erzeugt werden , gering ist , so viel von der Lektüre von /dev/random wird abgewürgt auf Zufälligkeit zu warten.

Sie könnten die Verwendung von random.org oder seines Passwortgenerators in Betracht ziehen , oder einen der vielen, vielen zufälligen Passwortgeneratoren, die in Umlauf sind. Schauen Sie sich zB diese Seite für ein paar Befehlszeilentipps an (nicht, dass ich alle empfehlen würde , aber sie sollten dir Ideen geben), oder du könntest so etwas benutzen mkpasswd(1)(hier auf Fedora 19 Teil von expect-5.45-8.fc19.x86_64).

vonbrand
quelle