W niektórych zastosowaniach potrzeby jest wydajny generator liczb losowych, chociaż zazwyczaj wystarczy po prostu wydajny generator liczb pseudolosowych (PRNGs). Dotyczy to np. instalacji serwerów i nod'ów Oracle WebLogic. Ponieważ oryginalny generator liczb pseudolosowych zawarty w jądrze Linux'a jest mało wydajny dokumentacja Oracle poleca tu następujące rozwiązanie:
https://docs.oracle.com/cd/E13209_01/wlcp/wlss30/configwlss/jvmrand.html
Jak jest wydajność standardowego generatora liczb pseudolosowych zawartego w jądrze Linux'a uruchomionego na zwirtualizowanym serwerze? Jak duży jest to problem? Na poniższym screenie można zobaczyć wynik zapytania o milion bajtów pseudolosowych do urządzenia /dev/random. Po prawie 10 minutach przerwałem tą operację uzyskawszy 232 bajty.
Tak, przez 10 minut otrzymałem 232 liczby pseudolosowe o wielkości jednego bajta, gdyż do ich generowania /dev/random wykorzystuje zasób entropii o wielkości 4096 bitów. Gdy ta pula zostanie wyczerpana pobieranie danych z /dev/random zatrzymuje się. Wielkość tego bufora jest ustawiona w /drivers/char/random.c:
#define INPUT_POOL_WORDS 128
#define OUTPUT_POOL_WORDS 32
(INPUT_POOL_WORDS * OUTPUT_POOL_WORDS ---> 128 * 32 = 4096 b).
W nowszych kernelach wielkość tego buforu jest kontrolowana przez /proc, a nadal pozostaje problem zapełnienia tego bufora entropii - wynika to z deterministycznego charakteru działania komputera, co przecież normalnie jest bardzo pożądane. Uzyskanie obliczeniowo bezpiecznych danych wymaga około 256 bitów entropii (32 bajty), a często wystarczy połowa tego.
Mimo tak marnej wydajności standardowego generatora rozwiązanie proponowane zarówno przez firmę Oracle, jak i przez inne źródła internetowe, a polegające na użyciu urządzenia /dev/urandom (od unblocking), jest według mnie bardzo niewskazane. Generator skojarzony z /dev/random daje liczby pseudolosowe o wysokiej odporności na przewidywalność kolejnych danych. Jednak ziarna używane do ich generacji nie są pozyskiwane ze źródeł o dużej wydajności, a jest to szczególnie trudne w środowisku zwirtualizowanym.
Więcej o "/dev/random":
Użycie urządzenia /dev/urandom (używającego funkcji skrótu na danych z pobranych /dev/random) jako obejście tego problemu daje liczby pseudolosowe, o nieakceptowalnej przewidywalności przez wiele aplikacji, jak np.: np. OpenSSL, PGP i GnuPG. Aplikacje te polegają na pobraniu "soli" (ang. seed) z /dev/random i na tej podstawie generują pseudolosowe ciągi bitów. Mimo tego to właśnie /dev/urandom jest preferowanym urządzeniem w Linuksie. Z kolei w FreeBSD (OS X) urządzenie /dev/urandom jest dokładnie tym samym urządzeniem, co /dev/urandom.
Warto zaznaczyć, że
/dev/urandom jest nieblokujący i poda zawsze tyle danych ile zostanie zażądane. Urządzenie to używa pseudolosowy generator liczb Yarrow. Gdy bufor entropii zostanie wyczerpany dane są generowane w cyklu, tak więc po wygenerowaniu 2^160 ~ = 1,5x10^48 bitów dane zaczną się powtarzać. Dla przykładu 1 ZB ~= 1.2x10^21 (
zettabajt).
Warto jeszcze zaznaczyć, że obsługa urządzeń pseudolosowych i pozwalających uzyskać dane dla bufora entropii zmienia się wraz z wersjami kernela.
Np. na lewym schemacie widać obsługę /dev/random i /dev/urandom przez kernele przed wersją 4.8, a na prawym od wersji 4.8:
Cześć praktyczna:
Na trzech serwerach:
bibi, jenna i
sasha bez modyfikacji generatora liczb pseudolowosych z kernela 3.10.0-327.10.1.el7.x86_64, pula entropii wynosi odpowiednio:
Gdy zaczniemy pobierać dane z /dev/random to uzyskamy na tych zwirtualizowanych serwerach tylko kilkanaście bajtów i wyczerpiemy zawartość bufora entropii:
Serwer
sasha:
Serwer
bibi:
Serwer
jenna:
W takiej sytuacji standardowym postępowaniem jest instalacja "rng-tools":
yum install rng-tools
service rngd start
service rngd status
|
Teraz możemy wykonać test, jak na poniższym screenie:
Niestety, nie sprawdzi się to w niektórych sytuacjach. Głównym problemem jest wirtualizacja, gdzie powyższe polecenie nie zakończy się w sensownym czasie. Rozwiązań może być kilka. Przykładowo dla VMware ESXi należy ustawić
monitor_control.virtual_rdtsc = "FALSE". Innym rozwiązaniem jest użycie kernela w wersji od 3.5 (z obsługa RDRAND). Gdy nie używamy VMware, lub wymaganego kernela w naszej dystrybucji, możemy zainstalować program "
haveged" (
http://www.issihosts.com/haveged/):
#yum install epel-release
yum install haveged
systemctl enable haveged
systemctl start haveged
systemctl status haveged
|
Po instalacji "haveged" i sprawdzeniu buforów entropi na serwerach bibi, sasha i jenna, oraz wykonaniu "cat /dev/random | rngtest -c 1000", uzyskamy poniższe wyniki:
Przydatne komendy do testów:
cat /dev/random
cat /dev/urandom
#
time cat /dev/random | rngtest -c 1000
time cat /dev/urandom | rngtest -c 1000
#
cat /proc/sys/kernel/random/entropy_avail
watch -n 1 cat /proc/sys/kernel/random/entropy_avail
|
Teraz pobieranie danych z /dev/rand nie jest spowolnione, a poniżej widać wielkość bufora entropii w trakcie takiego pobierania danych na serwerze bibi:
Wobec tego w większości systemów nie bedzie potrzeby modyfikacji źródła danych pseudolosowych dla WebLogic'a:
Możemy nawet sprawdzić z jaką szybkością będziemy mogli pobrać 1000000 bajtów z /dev/random i /dev/urandom:
dd if =/dev/random of=/dev/ null count= 1000000 bs= 1
|
Gdy systemy i wirtualizacja stosowana przez klienta uniemożliwia zastosowanie wydajnych algorytmów pseudolosowych (PRNGs), lub gdy klient wymaga prawdziwego generatora liczb losowych (TRNGs) w zwirtualizowanych systemach, można wykonać następująca instalację rozproszoną.
W serwerowni klienta, lub innej, instalujemy serwer przeznaczony do generowania licz losowych. Powinien to być serwer bez wirtualizacji, gdy opieramy się o dane zbierane z jego podzespołów, lub serwer zwirtualizowany, ale z dostępem do portów USB (dla USB 1.1 mamy znaczące ograniczenie wydajności). Taki centralny serwer można też wykonać jako serwer zbierający dane potrzebne do uzyskania wysokiej jakości generowanych liczb losowych z rozproszonych agentów. Jako agentów do takiego systemu można użyć wielu uwierzytelnionych komputerów połączonych szyfrowaną siecią. Dane mogą być generowane na podstawie np.:
1) Z kart dźwiękowych.
2) Modułów TPM.
3) Pamięci cache procesora.
4) Nowe procesory mają odpowiednie instrukcje.
Losowe liczby generowane z wielu agentów mogą następnie być dystrybuowane, również szyfrowanymi i uwierzytelnionymi kanałami, do farm serwerów i nod'ów obliczeniowych. Dzięki takiemu rozwiązaniu można mieć centralne źródło liczb losowych. Łatwiej jest je wyposażyć w odpowiedniej jakości sprzętowy generator liczb losowych, łatwiej dbać o oprogramowanie i bezpieczeństwo systemu.
Można też użyć dedykowanego sprzętu opartego np. o takie zjawiska fizyczne jak np.:
Szum termiczny - dla idealnego opornika jest to szum biały. Opisuje to wzór Johnsona-Nyquista na wartość średniokwadratową napięcia szumu termicznego na zaciskach opornika, który jest zasadniczo zgodny z jednowymiarową wersją prawa Plancka promieniowania ciała doskonale czarnego (promieniowanie elektromagnetyczne ciała czarnego w jednym wymiarze).
- Szum wahań termodynamicznych naładowania kondensatora (detekcja np. w obwodzie RC).
- Efekt fotoelektryczny.
- Szum złącza P-N.
Można również oprzeć generator liczb losowych o szerokopasmowe zakłócenia EM i RFI , szum promieniowania kosmicznego (np.: Drogi Mlecznej), szum kwantyzacji, losowość niezainicjalizowanej pamięci RAM. Jak widać starano się wykorzystać wszelkie możliwości, a czym tańsze i prostsze w implementacji tym lepiej. Poniżej kilka przykładów sprzętowych implementacji generatorów liczb losowych:
***
Inne wpisy:
Update: 2018.07.17
Create: 2018.07.17