Zum Hauptinhalt springen

7.1.2. The /dev/random Device (Das /dev/random-Gerät)

7.1.2. The /dev/random Device (Das /dev/random-Gerät)

Mehrere Versionen des UNIX-Betriebssystems bieten einen kernel-residenten Zufallszahlengenerator. Einige dieser Generatoren verwenden Ereignisse, die vom Kernel während des normalen Systembetriebs erfasst werden.

Zum Beispiel besteht der Generator auf einigen Versionen von Linux aus einem Zufallspool von 512 Bytes, dargestellt als 128 Wörter von jeweils 4 Bytes. Wenn ein Ereignis auftritt, wie ein Festplatteninterrupt, wird die Zeit des Ereignisses in den Pool XOR-verknüpft, und der Pool wird über ein primitives Polynom vom Grad 128 gerührt. Der Pool selbst wird als Ringpuffer behandelt, wobei neue Daten (nach dem Rühren mit dem Polynom) über den gesamten Pool XOR-verknüpft werden.

Jeder Aufruf, der Entropie zum Pool hinzufügt, schätzt die Menge der wahrscheinlichen echten Entropie, die die Eingabe enthält. Der Pool selbst enthält einen Akkumulator, der die Gesamtentropie über den gesamten Pool schätzt.

Eingabeereignisse stammen aus mehreren Quellen, wie unten aufgelistet. Leider sind für Servermaschinen ohne menschliche Betreiber die erste und dritte nicht verfügbar, und Entropie kann in diesem Fall langsam hinzugefügt werden.

  1. Tastatur-Interrupts. Die Zeit des Interrupts und der Scan-Code werden zum Pool hinzugefügt. Dies fügt effektiv Entropie vom menschlichen Betreiber hinzu, indem Ankunftszeiten zwischen Tastenanschlägen gemessen werden.

  2. Festplattenfertigstellung und andere Interrupts. Ein System, das von einer Person verwendet wird, wird wahrscheinlich ein schwer vorhersagbares Muster von Festplattenzugriffen haben. (Aber nicht alle Festplattentreiber unterstützen die Erfassung dieser Timing-Informationen mit ausreichender Genauigkeit, um nützlich zu sein.)

  3. Mausbewegung. Das Timing und die Mausposition werden hinzugefügt.

Wenn zufällige Bytes erforderlich sind, wird der Pool mit SHA-1 [SHA*] gehasht, um die zurückgegebenen Bytes an Zufälligkeit zu ergeben. Wenn mehr Bytes erforderlich sind als die Ausgabe von SHA-1 (20 Bytes), dann wird die gehashte Ausgabe zurück in den Pool gerührt und ein neuer Hash wird durchgeführt, um die nächsten 20 Bytes zu erhalten. Wenn Bytes aus dem Pool entfernt werden, wird die Schätzung der Entropie entsprechend dekrementiert.

Um einen vernünftig zufälligen Pool beim Systemstart sicherzustellen, speichern die Standard-Start- und Herunterfahrskripte den Pool in eine Datei auf der Festplatte beim Herunterfahren und lesen diese Datei beim Systemstart.

Es gibt zwei für Benutzer exportierte Schnittstellen. /dev/random gibt Bytes aus dem Pool zurück, blockiert aber, wenn die geschätzte Entropie auf null fällt. Wenn Entropie aus Ereignissen zum Pool hinzugefügt wird, werden mehr Daten über /dev/random verfügbar. Zufallsdaten, die von einem solchen /dev/random-Gerät erhalten werden, sind für die Schlüsselerzeugung für langfristige Schlüssel geeignet, wenn genügend zufällige Bits im Pool vorhanden sind oder in angemessener Zeit hinzugefügt werden.

/dev/urandom funktioniert wie /dev/random; es liefert jedoch Daten, selbst wenn die Entropieschätzung für den Zufallspool auf null fällt. Dies kann für Sitzungsschlüssel oder für andere Schlüsselerzeugungsaufgaben ausreichend sein, bei denen das Blockieren zum Warten auf mehr zufällige Bits nicht akzeptabel ist. Das Risiko, weiterhin Daten zu entnehmen, selbst wenn die Entropieschätzung des Pools klein ist, besteht darin, dass vergangene Ausgaben aus aktueller Ausgabe berechenbar sein können, vorausgesetzt, ein Angreifer kann SHA-1 umkehren. Da SHA-1 so entworfen wurde, dass es nicht invertierbar ist, ist dies ein vernünftiges Risiko.

Um Zufallszahlen unter Linux, Solaris oder anderen UNIX-Systemen zu erhalten, die mit Code wie oben beschrieben ausgestattet sind, muss eine Anwendung nur entweder /dev/random oder /dev/urandom öffnen und die gewünschte Anzahl von Bytes lesen.

(Das Linux Random Device wurde von Theodore Ts'o geschrieben. Es basierte lose auf dem Zufallszahlengenerator in PGP 2.X und PGP 3.0 (aka PGP 5.0).)