Was hält die Entropie ab?

21

Wenn ich das watch cat /proc/sys/kernel/random/entropy_availsehe, steigt die Entropie meines Systems mit der Zeit langsam an, bis sie den Bereich von 180-190 erreicht und dann auf etwa 120-130 abfällt. Die Entropietropfen scheinen etwa alle zwanzig Sekunden aufzutreten. Ich beobachte dies auch dann, wenn lsofgesagt wird, dass kein Prozess offen /dev/randomoder hat /dev/urandom. Was entzieht der Entropie? Benötigt der Kernel auch Entropie oder verarbeitet er den größeren Pool in einen kleineren Pool mit besserer Qualität?

Dies ist eine Bare-Metal-Maschine ohne SSL / SSH / WPA-Verbindungen.

wingedsubmariner
quelle
Gute Frage, und obwohl ich Ihnen keine konkrete Antwort geben kann, macht es für mich Sinn, dass der "Entropiepool" nicht einfach etwas ist, das sich erhöhen sollte, wenn er nicht verwendet wird. /dev/randomist schließlich etwas, das für sichere kryptografische Zwecke verwendet wird, und die Implementierung kann es sich nicht leisten, naiv zu sein. Eine Erklärung könnte im letzten Punkt hier angedeutet werden: de.wikipedia.org/wiki/Entropy_pool#Using_observed_events (beginnend mit "Verwalten einer Stream-Chiffre mit einem Schlüssel und einem Initialisierungsvektor ...") -> Der Pool wird immer dann ersetzt, wenn es ausreicht Daten haben sich angesammelt.
Goldlöckchen
Beachten Sie, dass die Linux-Entropieberechnung/dev/random in jedem Fall ziemlich falsch ist - wenn der Entropiepool einmal voll ist, /dev/urandomist sie genauso gut wie /dev/random.
Gilles 'SO- hör auf böse zu sein'
1
@techraf Wow, diese Antwort wurde schnell groß. Ich hätte nie gedacht, 2,5 Jahre später eine Antwort zu bekommen.
Wingedsubmariner

Antworten:

20

Entropie geht nicht nur über verloren /dev/{,u}random, der Kernel nimmt auch einige auf. Beispielsweise haben neue Prozesse zufällige Adressen (ASLR) und Netzwerkpakete benötigen zufällige Folgenummern. Sogar das Dateisystemmodul kann Entropie entfernen. Siehe die Kommentare in drivers / char / random.c . Beachten Sie auch, dass entropy_availsich dies auf den Eingabe-Pool bezieht , nicht auf die Ausgabe-Pools (im Grunde genommen nicht blockierend /dev/urandomund blockierend /dev/random).

Wenn Sie den Entropiepool überwachen müssen, verwenden Sie nicht watch cat, da dieser bei jedem Aufruf von Entropie verbraucht cat. In der Vergangenheit wollte ich auch diesen Pool beobachten, da GPG beim Generieren von Schlüsseln sehr langsam war. Deshalb schrieb ich ein C-Programm mit dem einzigen Zweck, den Entropiepool zu beobachten: https://git.lekensteyn.nl/c-files/tree /entropy-watcher.c .

Beachten Sie, dass es Hintergrundprozesse geben kann, die auch Entropie verbrauchen. Mithilfe von Tracepoints auf einem geeigneten Kernel können Sie die Prozesse anzeigen, die den Entropiepool ändern. Beispielverwendung, bei der alle mit dem zufälligen Subsystem zusammenhängenden Tracepoints aufgezeichnet werden, einschließlich der Callchain ( -g) auf allen CPUs ( -a), die nach 1 Sekunde mit der Messung beginnen, um ihren eigenen Prozess ( -D 1000) zu ignorieren, und einschließlich Zeitstempel ( -T):

sudo perf record -e random:\* -g -a -D 1000 -T sleep 60

Lesen Sie es mit einem dieser Befehle (ändern Sie den Eigentümer perf.datanach Bedarf):

perf report  # opens an interactive overview
perf script  # outputs events after each other with traces

Die perf scriptAusgabe gibt einen interessanten Einblick und zeigt, wann in regelmäßigen Abständen ca. 8 Byte (64 Bit) Entropie auf meinem Computer verbraucht werden:

kworker / 0: 2 193 3292.235908: random: extract_entropy: ffffffff8173e956 pool: nbytes 8 entropy_count 921 caller _xfer_secondary_pool
                  5eb857 extract_entropy (/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  5eb984 _xfer_secondary_pool (/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  5ebae6 push_to_pool (/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  293a05 process_one_work (/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  293ce8 worker_thread (/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  299998 kthread (/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  7c7482 ret_from_fork (/lib/modules/4.6.2-1-ARCH/build/vmlinux)

kworker / 0: 2 193 [000] 3292.235911: random: debit_entropy: ffffffff8173e956: debit_bits 64
                  5eb3e8 account.part.12 (/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  5eb770 extract_entropy (/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  5eb984 _xfer_secondary_pool (/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  5ebae6 push_to_pool (/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  293a05 process_one_work (/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  293ce8 worker_thread (/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  299998 kthread (/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  7c7482 ret_from_fork (/lib/modules/4.6.2-1-ARCH/build/vmlinux)

...

swapper 0 3292.507720: random: credit_entropy_bits: ffffffff8173e956 pool: bits 2 entropy_count 859 entropy_total 2 caller add_interrupt_randomness
                  5eaab6 credit_entropy_bits (/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  5ec644 add_interrupt_randomness (/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  2d5729 handle_irq_event_percpu (/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  2d58b9 handle_irq_event (/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  2d8d1b handle_edge_irq (/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  230e6a handle_irq (/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  7c9abb do_IRQ (/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  7c7bc2 ret_from_intr (/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  6756c7 cpuidle_enter (/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  2bd9fa call_cpuidle (/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  2bde18 cpu_startup_entry (/lib/modules/4.6.2-1-ARCH/build/vmlinux)
                  2510e5 start_secondary (/lib/modules/4.6.2-1-ARCH/build/vmlinux)

Anscheinend geschieht dies, um eine Verschwendung von Entropie zu verhindern, indem Entropie vom Eingabepool in Ausgabepools übertragen wird:

/*
 * Credit (or debit) the entropy store with n bits of entropy.
 * Use credit_entropy_bits_safe() if the value comes from userspace
 * or otherwise should be checked for extreme values.
 */
static void credit_entropy_bits(struct entropy_store *r, int nbits)
{
    ...
        /* If the input pool is getting full, send some
         * entropy to the two output pools, flipping back and
         * forth between them, until the output pools are 75%
         * full.
         */

         ...
            schedule_work(&last->push_work);
}

/*
 * Used as a workqueue function so that when the input pool is getting
 * full, we can "spill over" some entropy to the output pools.  That
 * way the output pools can store some of the excess entropy instead
 * of letting it go to waste.
 */
static void push_to_pool(struct work_struct *work)
{
    ...
}
Lekensteyn
quelle
2
+1 für den Hinweis, dass selbst scheinbar "harmlose" Operationen wie das Starten eines Programms eine geringe Menge an Entropie verbrauchen können.
ein Lebenslauf vom
Diese Erklärung ist jedoch ein bisschen widersprüchlich zu der in der Frage beschriebenen Situation, nicht wahr? Dort watchwächst die Entropie (überwacht mit ) stetig und fällt dann scharf ab. Wenn watchbei jedem Messwert Entropie verbraucht wird, sollte diese tatsächlich stetig abnehmen.
Techraf
@techraf Gute Beobachtung, periodisches Aufrufen catsollte theoretisch den gleichen Entropiedrain haben, der nicht sichtbar sein sollte. Es stellt sich heraus, dass die Entropie in einen anderen Pool verschoben wird, wenn "genügend" Entropie vorhanden ist.
Lekensteyn
4

lsof ist nicht das beste Tool zum Überwachen,/dev/randomda ein Lesevorgang durch einen Prozess in sehr kurzer Zeit abgeschlossen ist. Ich kenne keine gute Methode, um herauszufinden, welcher Prozess einen Lesevorgang durchführt, aber mithilfe von könneninotifySie überwachen, ob es einen Lesevorgang gibt.

Hier gibt es grundsätzlich zwei Möglichkeiten:

  1. Erhalten Sie eine Zusammenfassung nach N Sekunden mit:

    inotifywatch -v -t 60 /dev/random 
    
  2. Sehen Sie Live - Zugang Veranstaltungen:

    inotifywait -m --timefmt '%H:%M:%S' --format '%T: %e' /dev/random
    

Weder geben Sie Prozess und Letzteres wird Ihnen nicht die Größe des Lesens geben. Der erste gibt Ihnen eine Zusammenfassung wie in:

total  access  close_nowrite  open  filename
18     16      1              1     /dev/random

Wenn Sie das laufen lassen und a tun dd if=/dev/random of=/tmp/foo bs=1 count=3, erhalten Sie die Idee.

Jedenfalls. Dies gibt Ihnen keine Ticks, wenn der Kernel aus dem Pool konsumiert.


Wenn es darum geht, den Status der Entropie mit zu überprüfen

watch cat /proc/sys/kernel/random/entropy_avail

ist nicht die beste Idee, da jeder catEntropie verbrauchen wird. (Ich sehe jetzt, dass eine andere Antwort auftaucht, die dies ebenfalls erwähnt.) Ich habe auch einen C-Code dafür und habe gestern versucht, ihn zu finden. Ich werde sehen, ob ich es finden und die Antwort später aktualisieren kann.

Runium
quelle
auditd kann Lesevorgänge protokollieren /dev/random(ich weiß, dass es auf dieser Site ähnliche Beispiele gibt).
Gilles 'SO - hör auf, böse zu sein'
1
Was ist mit der Verwendung der folgenden Perl anstelle von watch cat: use Fcntl 'SEEK_SET'; open(my $fh,"<", "/proc/sys/kernel/random/entropy_avail"); while (1) { print <$fh>; sleep(1); seek($fh,0,SEEK_SET); }
gmatht