Entropia jest nie tylko tracona przez /dev/{,u}random
jądro, ale także i jądro. Na przykład nowe procesy mają adresy losowe (ASLR), a pakiety sieciowe potrzebują losowych numerów sekwencji. Nawet moduł systemu plików może usunąć trochę entropii. Zobacz komentarze w drivers / char / random.c . Zauważ też, że entropy_avail
odnosi się to do puli wejściowej , a nie pul wyjściowych (w zasadzie nieblokujący /dev/urandom
i blokujący /dev/random
).
Jeśli chcesz obserwować pulę entropii, nie używaj watch cat
, ponieważ zużyje ona entropii przy każdym wywołaniu cat
. W przeszłości chciałem również oglądać tę pulę, ponieważ GPG bardzo wolno generowała klucze, dlatego napisałem program C, którego jedynym celem było obejrzenie puli entropii: https://git.lekensteyn.nl/c-files/tree /entropy-watcher.c .
Zauważ, że mogą istnieć procesy w tle, które również zużywają entropię. Używając tracepoints na odpowiednim jądrze, możesz zobaczyć procesy modyfikujące pulę entropii. Przykładowe użycie, które rejestruje wszystkie punkty śledzenia związane z losowym podsystemem, w tym callchain ( -g
) na wszystkich procesorach ( -a
), rozpoczynając pomiar po 1 sekundzie w celu zignorowania własnego procesu ( -D 1000
) i włączając znaczniki czasu ( -T
):
sudo perf record -e random:\* -g -a -D 1000 -T sleep 60
Przeczytaj to za pomocą jednego z poniższych poleceń (w perf.data
razie potrzeby zmień właściciela ):
perf report # opens an interactive overview
perf script # outputs events after each other with traces
Dane perf script
wyjściowe dają ciekawy wgląd i pokazują, kiedy około 8 bajtów (64 bitów) entropii jest okresowo usuwanych z mojej maszyny:
kworker / 0: 2 193 [000] 3292.235908: losowy: extract_entropy: ffffffff8173e956 pula: nbytes 8 entropy_count 921 rozmówca _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 [002] 3292.507720: losowy: bity_centralne_danych: ffffffff8173e956 pula: bity 2 entropia_liczenia 859 entropia_total 2 rozmówca 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 uchwyt_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)
Najwyraźniej dzieje się tak, aby zapobiec marnowaniu entropii, przenosząc entropię z puli wejściowej do pul wyjściowych:
/*
* 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)
{
...
}
/dev/random
jest przecież czymś, co jest wykorzystywane do bezpiecznych celów kryptograficznych, a implementacja nie może być naiwna. Jednym z wyjaśnień może być wskazany w ostatnim punkcie tutaj: en.wikipedia.org/wiki/Entropy_pool#Using_observed_events (zaczynając od „Zachowaj szyfr strumienia za pomocą klucza i wektora inicjalizacji ...”) -> pula jest zastępowana, ilekroć wystarczająca dane się zgromadziły.