Warum gibt dd from / dev / random unterschiedliche Dateigrößen an?

26

Ich führe den folgenden Befehl auf einem Ubuntu-System aus:

dd if=/dev/random of=rand bs=1K count=2

Bei jeder Ausführung erhalte ich jedoch eine Datei mit einer anderen Größe. Warum ist das? Wie kann ich eine Datei einer bestimmten Größe erzeugen, die mit zufälligen Daten gefüllt ist?

Daniel
quelle
1
/dev/randomwird blockiert, wenn nicht genügend Entropie zur Verfügung steht, um die gewünschte Anzahl von Ziffern zu generieren. Es braucht einfach Zeit, um die Menge der zufälligen "Zufälligkeit" von Pseudoqualität zu erfassen ... Verwenden Sie entweder /dev/urandomeinen weniger zufälligen "Zufall" -Wert oder überprüfen Sie Ihren Entropiepool (in einer Schleife und warten Sie nach Bedarf) ...
Peter.O
Siehe auch diese Frage .
Keith Thompson
3
einfach hinzufügeniflag=fullblock
frostschutz 23.03.15

Antworten:

31

Sie beobachten eine Kombination des besonderen Verhaltens von ddmit dem besonderen Verhalten von Linux /dev/random. Beide sind im Übrigen selten das richtige Werkzeug für den Job.

Linux /dev/randomgibt Daten sparsam zurück. Es wird davon ausgegangen, dass die Entropie im Pseudozufallszahlengenerator sehr schnell erlischt. Da das Sammeln neuer Entropie langsam ist, werden in der /dev/randomRegel nur wenige Bytes gleichzeitig freigegeben.

ddist ein altes, launisches Programm, das ursprünglich für Bandgeräte gedacht war. Wenn Sie ihm anweisen, einen Block von 1 KB zu lesen, wird versucht, einen Block zu lesen. Wenn der Lesevorgang weniger als 1024 Bytes zurückgibt, ist das alles, was Sie bekommen. Also dd if=/dev/random bs=1K count=2macht zwei read(2)Anrufe. Da von dort gelesen wird /dev/random, geben die beiden readAufrufe in der Regel nur wenige Bytes zurück, und zwar in unterschiedlicher Anzahl, abhängig von der verfügbaren Entropie. Siehe auch Wann eignet sich dd zum Kopieren von Daten? (oder wenn read () und write () partiell sind)

Sofern Sie kein Betriebssystem-Installationsprogramm oder -Kloner entwerfen, sollten Sie es niemals /dev/randomunter Linux verwenden /dev/urandom. Die urandomManpage ist etwas irreführend; /dev/urandomist in der Tat für die Kryptographie geeignet, auch um langlebige Schlüssel zu generieren. Die einzige Einschränkung dabei /dev/urandomist, dass es mit ausreichender Entropie versorgt werden muss; Linux-Distributionen speichern normalerweise die Entropie zwischen Neustarts, sodass Sie möglicherweise nur bei einer Neuinstallation nicht genügend Entropie haben. Entropie nutzt sich praktisch nicht ab. Weitere Informationen finden Sie unter Ist ein Rand aus / dev / urandom für einen Anmeldeschlüssel sicher? und Feeding / dev / random Entropy Pool? .

Die meisten Verwendungen von ddwerden besser mit Werkzeugen wie headoder ausgedrückt tail. Wenn Sie 2 KB zufällige Bytes möchten, führen Sie aus

head -c 2k </dev/urandom >rand

Mit älteren Linux-Kerneln könnten Sie davonkommen

dd if=/dev/urandom of=rand bs=1k count=2

weil /dev/urandomglücklich so viele Bytes wie angefordert zurückgegeben. Dies ist jedoch nicht mehr der Fall, da Kernel 3.16 auf 32 MB beschränkt ist .

Im Allgemeinen, wenn Sie verwenden müssen , ddeine feste Anzahl von Bytes und seine Eingabe kommt nicht von einer normalen Datei oder Block - Gerät zu extrahieren, müssen Sie Byte für Byte lesen: dd bs=1 count=2048.

Gilles 'SO - hör auf böse zu sein'
quelle
Vielen Dank für den Tipp, Head anstelle von dd zu verwenden. Das erlaubt mir, / dev / random trotzdem zu benutzen, wenn ich will. Obwohl / dev / urandom, wie Sie bereits erwähnt haben, wahrscheinlich ausreichen würde, ist es gut zu wissen, wie / dev / random verwendet wird, falls dies erforderlich sein sollte.
Daniel
auf Kerneln seit 3.16 /dev/urandom liefert 32m perread() .
mikeserv
Wenn Sie einen POSIX-kompatiblen Befehl benötigen, können Sie den folgenden Trick verwenden: unix.stackexchange.com/a/192114 dd if=/dev/urandom ibs=1k obs=1k | dd bs=1k count=2
Rufflewind,
11

Ab man 4 randomeiner RHEL 5 Box:

Beim Lesen gibt das Gerät / dev / random nur zufällige Bytes innerhalb der geschätzten Anzahl von Rauschbits im Entropiepool zurück.

Ich erhalte Dateien mit einer Größe von 213 Bytes auf diesem Computer. Zurück zu Mann 4 zufällig:

Beim Lesen gibt das Gerät / dev / urandom so viele Bytes zurück, wie angefordert werden.

Ich erhalte 2048 Bytes von jedem Aufruf von dd if=/dev/urandom of=rand bs=1K count=2

Ich schließe daraus, dass der Unterschied darauf zurückzuführen ist, wie viel Entropie Ihre Maschine zwischen den Aufrufen von erzeugt dd if=/dev/random ...

Bruce Ediger
quelle
Ja, praktisch sollte @Daniel / dev / urandom verwenden, es sei denn, er ist in einer echten Krypto-Anwendung. Aber ich bin verwirrt, warum es dd if=/dev/random bs=1K count=2aufhört, wenn der Entropiepool anscheinend leer ist. In den Dokumenten sollte es blockieren, bis mehr Entropie vorhanden ist, sodass die ddDatei langsam geschrieben wird, anstatt nur den aktuellen Pool zu löschen und zu beenden.
cjc
Darüber habe ich mich auch gewundert, aber es ist in RHEL, Slackware 13.1 und einem ziemlich aktuellen Arch konsistent. Der RHEL war x86_64, die anderen waren 32-Bit. Leider sind die dd-Dokumente im GNU-Info-Format, daher habe ich sie nicht alle gelesen.
Bruce Ediger
Dies gilt auch für Gentoo.
Matthew Scharley
4
@cjc: Es ist , weil Sie bei einem Anruf read(fd, mybuf, 1024)auf einer Blockierung FD gibt es, sobald das zugrunde liegende Gerät gibt einige Daten. Wenn dort 1024 Bytes gelesen werden müssen, wird dies zurückgegeben. Wenn es nur 201 Bytes gibt, wird 201 zurückgegeben. Wenn 0 Bytes verfügbar sind, wird blockiert, bis mindestens ein Byte verfügbar ist, und dann wird es / sie zurückgegeben.
Warren Young
@WarrenYoung leert das Lesen aus / dev / random seinen Inhalt? Ich gehe davon aus.
Michael Martinez
5

Warum werden ddDaten gelöscht? ... Gilles hat diese spannende Frage gestellt dd:
Wann ist dd zum Kopieren von Daten geeignet? (oder, wenn read () und write () partiell sind)
Hier ist ein Auszug aus dieser Frage:

    * ... es ist nicht schwer, dd zu beschuldigen; Versuchen Sie zum Beispiel diesen Code: **
        yes | dd of=out bs=1024k count=10
    und überprüfen Sie die Größe der Ausgangsdatei (wahrscheinlich liegt sie weit unter 10 MB).


Abgesehen von meinem Kommentar (am Ende Ihrer Frage) ist so etwas interessant zu beobachten ... Es fängt Ihre Bytes in der Datei ab $trnd. Ich habe halb willkürlich bs = 8 gewählt

Bewegen Sie die Maus und beobachten Sie, wie sie schneller wird.
Mit meinem Computer im Leerlauf (AFK und keine Netzwerkaktivität) und nachdem der Entropiepool erschöpft war, dauerte es 2 Stunden und 12 Minuten , um nur 1192 Bytes zu sammeln. Zu diesem Zeitpunkt habe ich ihn abgebrochen.

Wenn ich dann die Maus ununterbrochen bewegte, dauerte es relativ viel weniger als 1 Minute und 15 Sekunden , um die gleiche Anzahl von Bytes zu sammeln.

Dies zeigt ziemlich deutlich, dass das Sammeln von Entropie nicht auf der CPU-Geschwindigkeit basiert, sondern auf zufälligen Ereignissen , und dass mein Ubuntu-System die Maus als einen seiner signifikanten Zufallsfaktoren verwendet.

get=2048
trnd=/tmp/$USER.rnd; >"$trnd"
while (( $(wc -c <"$trnd") < $get )) ;do
    dd if=/dev/random bs=8 count=1 2>/dev/null >>"$trnd"
    echo -n "itt: $((i+=1))  ct: "; wc -c <"$trnd"
done
truncate -s $get "$trnd"
echo -e "\nfinal count: "; wc -c <"$trnd"
Peter.O
quelle
1

ddist konzipiert für das Blockieren - in der Regel das beste Werkzeug zur Verfügung , es zum Lesen von variabler Größe Eingaben ist , wenn Sie es getan müssen sofort da ddnicht aktuelle Puffer liest in eine Zukunft write() (wenn Sie sehr explizit mit größeren obs als ibs es so konfigurieren) , sondern write()alles, was es liest, sobald es read()ist (und optional verarbeitet) .

Hier sind einige wichtige Definitionen :

  • ibs=expr
    • Geben Sie die Größe des Eingabeblocks in Byte an (Standard ist 512) .expr
  • obs=expr
    • Geben Sie die Ausgabeblockgröße in Byte an (Standard ist 512) .expr
  • bs=expr
    • Stellen Sie sowohl die Eingabe- als auch die Ausgabeblockgröße auf exprBytes ein und ersetzen Sie ibs=und obs=. Wenn keine andere Konvertierung als sync, noerrorund notruncangegeben ist, wird jeder Eingabeblock als einzelner Block in die Ausgabe kopiert, ohne kurze Blöcke zu aggregieren.

Sie sehen also, wann ibsund obswie bsdann gemeinsam definiert werden, ibsaber ansonsten, wenn Sie spezifisch sind, entweder obsoder cbs.

Hier ist ein Beispiel, das ibsam wichtigsten ist. Sie könnten so etwas tun, wenn Sie nachverfolgen möchten, wie schnell sich der /dev/randomPool gefüllt hat ...

dd "ibs=$size" conv=sync "count=$lmt" \ 
    if=/dev/random of="$somefile"

Solange if=das Ziel überhaupt lesbar ist, führt dies immer zu einer Ausgabedatei mit derselben Größe, da dddas syncEinlesen von Blöcken auf Nullen verzögert wird. Mit anderen Worten, wenn dd read()s für einen Eingabeblock von $((size=10)) $((count=5))Zeiten ist und die read()Datei 2 Bytes zurückgibt, dann ddschreiben 8 Bytes, dann 12 Bytes, dann 2 Bytes, dann 4 Bytes in ihre Outfile wie

 2 read bytes 8NULs \
 8 read bytes 2NULs \
10 read bytes 0NULs \
 4 read bytes 6NULs \
 4 read bytes 6NULs

... weil ddstandardmäßig nicht verzögert. Wenn Sie also In-Streams verfolgen und die Schreibvorgänge eines anderen Prozesses eingrenzen müssen, ddist dies das richtige Werkzeug für Sie.

Wenn Sie nur eine gewisse Menge an Daten in eine reguläre Datei zu schreiben dann, im Gegensatz zu anderen Aussagen hier, können Sie auch ddfür diese - und ziemlich leicht - aber Sie brauchen mehr als einen und einen zuverlässigen Sperrfaktor .

Wenn Sie zum Beispiel Folgendes getan haben:

{   dd ibs="$size" obs="${size}x$block_factor" |
    dd bs="${size}x$blockfactor" "count=$lmt"
}  <infile >outfile

... würde der erste ddso viele ibs="$size"Eingabeblöcke puffern, wie nötig sind, um mindestens einen obs="${size}x$block_factor"Ausgabeblock für jeden write()zu der Pipe zwischen ihm und dem zweiten zu füllen dd. Dies bedeutet, dass der zweite dddie Ausgabe zuverlässig begrenzen kann, count="$lmt"da alle write()s des ersten Herstellers der E / A-Blockgröße entsprechen - unabhängig davon, wie viele read()s der erste dafür ddtun muss.

Auf diese Weise können Sie ddPipes oder andere Arten von Spezialdateien zuverlässig lesen - mit nur ein wenig Mathematik.

mikeserv
quelle