Jak sobie radzić z wolnym generatorem SecureRandom?

165

Jeśli chcesz mieć silne kryptograficznie liczby losowe w Javie, użyj SecureRandom. Niestety SecureRandommoże to być bardzo powolne. Jeśli używa /dev/randomw systemie Linux, może blokować oczekiwanie na zbudowanie wystarczającej entropii. Jak uniknąć spadku wydajności?

Czy ktoś użył Uncommon Maths jako rozwiązania tego problemu?

Czy ktoś może potwierdzić, że ten problem z wydajnością został rozwiązany w JDK 6?

David G.
źródło
Wygląda na to, że jest to związane z powolnością SecureRandom.generateSeed () . Istnieje odrzucona usterka wyjaśniająca powolność i obejście: JDK-6521844: SecureRandom zawiesza się w systemach Linux
AlikElzin-kilaka
Sprawdź / dev / urandom (nie / dev / random) .. Rozważ po prostu pobranie ziaren generatora liczb losowych od urandom, jeśli występuje problem z blokowaniem.
jcalfee314
Powiązane z systemem Windows: stackoverflow.com/questions/49322948/ ...
patrikbeno

Odpowiedzi:

79

Jeśli chcesz prawdziwych losowych danych, niestety musisz na to poczekać. Obejmuje to ziarno SecureRandomPRNG. Uncommon Maths nie może gromadzić prawdziwie losowych danych szybciej niż SecureRandom, chociaż może łączyć się z Internetem w celu pobrania danych początkowych z określonej witryny. Domyślam się, że prawdopodobnie nie będzie to szybsze niż /dev/randomtam, gdzie jest to dostępne.

Jeśli chcesz PRNG, zrób coś takiego:

SecureRandom.getInstance("SHA1PRNG");

Obsługiwane ciągi zależą od SecureRandomdostawcy SPI, ale można je wyliczyć za pomocą Security.getProviders()i Provider.getService().

Sun lubi SHA1PRNG, więc jest szeroko dostępny. Nie jest szczególnie szybki jak PRNG, ale PRNG będą po prostu przetwarzać liczby, a nie blokować fizycznego pomiaru entropii.

Wyjątkiem jest to, że jeśli nie zadzwonisz setSeed()przed pobraniem danych, PRNG uruchomi się po pierwszym wywołaniu next()lub nextBytes(). Zwykle robi to przy użyciu dość małej ilości prawdziwie losowych danych z systemu. To wywołanie może blokować, ale sprawi, że twoje źródło liczb losowych będzie o wiele bezpieczniejsze niż jakikolwiek wariant "mieszaj aktualny czas razem z PID, dodaj 27 i miej nadzieję na najlepsze". Jeśli jednak potrzebujesz tylko liczb losowych do gry lub jeśli chcesz, aby strumień był powtarzalny w przyszłości przy użyciu tego samego ziarna do celów testowych, niezabezpieczone ziarno jest nadal przydatne.

Steve Jessop
źródło
Niezbyt często Matematyka pobiera dane z Internetu tylko do inicjowania, nie zwraca tych losowych danych podczas generowania liczb losowych.
Dan Dyer,
To samo z SecureRandom - / dev / urandom służy tylko do seedowania.
AviD,
Tak. Kiedy pytający mówi „jeśli chcesz losową liczbę, użyj SecureRandom - to może być powolne”, pomyślałem, że może używa getSeed do wszystkiego i opróżnia swoją pulę entropii. Poprawka nie polega na uzyskaniu JDK 6, ale na używaniu SecureRandom zgodnie z przeznaczeniem ;-)
Steve Jessop
@Dan Dyer - poprawiłem swój komentarz dotyczący Uncommon Maths. Rzuciłem okiem na twoją stronę, więc wiedziałem, że przez „liczby losowe” miałem na myśli raczej „jako materiał źródłowy” niż „powrót do użytkownika”. Ale masz rację, to nie to, co powiedziałem ...
Steve Jessop
„jest powszechnie dostępny”. Czy nie jest dołączony do każdego zgodnego JDK? Znajduje się na liście nazw standardów bezpieczeństwa Java ... ( docs.oracle.com/javase/8/docs/technotes/guides/security/ ... )
Sean Reilly
176

Powinieneś być w stanie wybrać szybszy, ale nieco mniej bezpieczny / dev / urandom w systemie Linux za pomocą:

-Djava.security.egd=file:/dev/urandom

Jednak to nie działa z Javą 5 i nowszymi wersjami ( błąd Java 6202721 ). Sugerowanym obejściem jest użycie:

-Djava.security.egd=file:/dev/./urandom

(uwaga na dodatek /./)

Thomas Leonard
źródło
24
Zwróć uwagę, że raport o błędzie Java zawiera komunikat „To nie jest usterka”. Innymi słowy, chociaż domyślnym jest to /dev/urandom, Sun traktuje to jako magiczny ciąg i /dev/randomtak czy inaczej używa , więc musisz go sfałszować. Kiedy file:adres URL nie jest file:adresem URL? Kiedy Sun zdecyduje, że nie jest :-(
Jim Garrison,
6
Spędziwszy właśnie trochę czasu na badaniu tego, wydaje się, że normalne ustawienie, nawet jeśli jest file:/dev/urandomustawione w -Djava.security.egdlub w securerandom.sourcepliku java.security, /dev/random/jest nadal odczytywane SecureRandom.getSeed()(lub setSeed()jest wywoływane). Obejście problemu z file:/dev/./urandomwynikiem w ogóle nie czytającym /dev/random(potwierdzonym strace)
mat b
7
/dev/urandomnie jest mniej bezpieczny niż /dev/randompo wdrożeniu za pomocą nowoczesnego CSPRNG: en.wikipedia.org/wiki//dev/random#FreeBSD
lapo
Myślę, że główną obawą /dev/urandom/jest to, co się stanie, jeśli użyjesz go do wygenerowania sekretów na nowym sprzęcie po wyjęciu z pudełka, który może być w dość przewidywalnym stanie. /dev/urandom/nie blokuje entropii, mimo że jest to jeden przypadek, w którym powinieneś. Sytuacja jest jeszcze gorsza, jeśli sekret jest trwały, na przykład jeśli pierwszą rzeczą, którą urządzenie robi przy pierwszym uruchomieniu, jest wygenerowanie pary kluczy publiczny-prywatny. Poza tymi przerażającymi sytuacjami, i tak dobre /dev/urandomjest lepsze niż używanie zwykłych SecureRandomalgorytmów.
Steve Jessop
1
Który jest prawidłowy ? -Djava.security.egd = file: / dev /./ urandom lub file: /// dev / urandom @mattb
Aarish Ramesh
35

W Linuksie domyślna implementacja dla SecureRandomto NativePRNG( tutaj kod źródłowy ), która zwykle działa bardzo wolno. W systemie Windows wartość domyślna to SHA1PRNG, której, jak wskazywali inni, można również używać w systemie Linux, jeśli wyraźnie to określisz.

NativePRNGróżni się od SHA1PRNGi Uncommons Maths AESCounterRNG tym, że stale otrzymuje entropię z systemu operacyjnego (czytając z /dev/urandom). Pozostałe PRNG nie uzyskują żadnej dodatkowej entropii po zaszczepieniu.

AESCounterRNG jest około 10x szybszy niż SHA1PRNGIIRC, który sam jest dwa lub trzy razy szybszy niż NativePRNG.

Jeśli potrzebujesz szybszego PRNG, który uzyskuje entropię po inicjalizacji, sprawdź, czy możesz znaleźć implementację Fortuny w Javie . Podstawowy PRNG implementacji Fortuny jest identyczny z tym używanym przez AESCounterRNG, ale istnieje również wyrafinowany system pulowania entropii i automatycznego ponownego zasiewu.

Dan Dyer
źródło
Ten link nie działa. uncommons-maths.dev.java.net/nonav/api/org/uncommons/maths/… . Czy gdzieś mogę to zobaczyć?
UVM
@Unni Właśnie zaktualizowałem link. Należy pamiętać, że twierdzenia dotyczące wydajności, które przedstawiłem w tej odpowiedzi, mogą być już nieaktualne. Myślę, że w ostatnich wersjach Java mogło się poprawić i mogą występować różnice w wydajności między platformami (np. Windows kontra Liux).
Dan Dyer,
Właśnie uruchomiłem jeden przykład SecureRandom z MessageDigest i zakodowałem go szesnastkowo. Cała operacja na moim komputerze z systemem Windows 7 zajęła 33 milisekundy. Czy to problem. Użyłem SHA1PRNG.SecureRandom prng = SecureRandom.getInstance ("SHA1PRNG"); String randomNum = new Integer (prng.nextInt ()) .toString (); MessageDigest sha = MessageDigest.getInstance ("SHA-1"); result = sha.digest (randomNum.getBytes ()); str = hexEncode (wynik);
UVM
24

Wiele dystrybucji Linuksa (głównie opartych na Debianie) konfiguruje OpenJDK do wykorzystania /dev/randomw entropii.

/dev/random jest z definicji powolny (a nawet może blokować).

Tutaj masz dwie opcje odblokowania:

  1. Popraw entropię lub
  2. Zmniejsz wymagania dotyczące losowości.

Opcja 1, Popraw entropię

Aby uzyskać więcej entropii /dev/random, wypróbuj zniszczonego demona. Jest to demon, który w sposób ciągły zbiera entropię HAVEGE i działa również w środowisku zwirtualizowanym, ponieważ nie wymaga żadnego specjalnego sprzętu, a jedynie sam procesor i zegar.

W systemie Ubuntu / Debian:

apt-get install haveged
update-rc.d haveged defaults
service haveged start

Na RHEL / CentOS:

yum install haveged
systemctl enable haveged
systemctl start haveged

Opcja 2. Zmniejsz wymagania dotyczące losowości

Jeśli z jakiegoś powodu powyższe rozwiązanie nie pomoże lub nie zależy Ci na silnej kryptograficznie losowości, możesz /dev/urandomzamiast tego przełączyć się na , co gwarantuje, że nie zostanie zablokowany.

Aby to zrobić globalnie, edytuj plik jre/lib/security/java.securityw domyślnej instalacji Java do użycia /dev/urandom(z powodu innego błędu należy go określić jako /dev/./urandom).

Lubię to:

#securerandom.source=file:/dev/random
securerandom.source=file:/dev/./urandom

Wtedy nigdy nie będziesz musiał podawać tego w wierszu poleceń.


Uwaga: jeśli zajmujesz się kryptografią, potrzebujesz dobrej entropii. Sprawa w punkcie - android problem PRNG zmniejszone bezpieczeństwo portfele Bitcoin.

rustyx
źródło
Głosowałeś za twoją odpowiedzią, ale „ /dev/randomz definicji jest powolny (i może nawet blokować)” jest błędny; zależy to całkowicie od konfiguracji systemu. Nowsze maszyny mogą mieć np. Szybki RNG w CPU, który może być używany, a maszyny BSD mają generalnie tę samą implementację dla /dev/randomi /devl/urandom. Mimo to prawdopodobnie nie powinieneś polegać na /dev/random szybkości. W przypadku maszyn wirtualnych możesz chcieć zainstalować zestaw narzędzi klienta na maszynie wirtualnej klienta, aby można było używać RNG systemu operacyjnego hosta.
Maarten Bodewes
17

Miałem podobny problem z wezwaniami do SecureRandomblokowania przez około 25 sekund na raz na bezgłowym serwerze Debiana. Zainstalowałem havegeddemona, aby mieć pewność, że /dev/randomjest doładowany, na serwerach bezgłowych potrzebujesz czegoś takiego, aby wygenerować wymaganą entropię. Moje telefony do SecureRandomtej pory mogą zająć milisekundy.

grzmot
źródło
4
apt-get install haveged, a następnie update-rc.d haveged defaults
Rod Lima
11

Jeśli chcesz naprawdę „kryptograficznie silnej” losowości, potrzebujesz silnego źródła entropii. /dev/randomjest powolny, ponieważ musi czekać, aż zdarzenia systemowe zgromadzą entropię (odczyty dysku, pakiety sieciowe, ruchy myszy, naciśnięcia klawiszy itp.).

Szybszym rozwiązaniem jest sprzętowy generator liczb losowych. Być może masz już jeden wbudowany w płytę główną; zapoznaj się z dokumentacją hw_random, aby dowiedzieć się, czy go masz i jak go używać. Pakiet rng-tools zawiera demona, który będzie dostarczał wygenerowaną sprzętowo entropię do /dev/random.

Jeśli HRNG nie jest dostępny w twoim systemie i jesteś gotów poświęcić siłę entropii na rzecz wydajności, będziesz chciał obsiać dobry PRNG danymi z /dev/randomi pozwolić PRNG wykonać większość pracy. Istnieje kilka zatwierdzonych przez NIST PRNG wymienionych w SP800-90, które są łatwe do wdrożenia.

Chris Kite
źródło
Słuszna uwaga, ale mój kod jest częścią aplikacji komercyjnej. Nie mam żadnej kontroli nad środowiskiem serwera. Myślę, że docelowe serwery są zawsze bez myszy i klawiatury i polegają całkowicie na dysku i sieci we / wy dla entropii, która jest prawdopodobnie głównym problemem.
David G
3
Odkryłem, że / dev / random było zależne od zdarzeń systemowych, więc jako tymczasowe obejście po prostu poruszałem myszą w przód iw tył, podczas gdy mój test był wykonywany ...
David K,
Ten hub 82802 dla chipsetu i820 był boleśnie wolny (RIP). Jestem zdumiony, że udało ci się zebrać z niego cokolwiek pożytecznego. Myślę, że spędziłem więcej czasu na blokowaniu, niż zbieraniu oktetów.
jww
6

Używając Java 8, odkryłem, że w Linuksie wywołanie SecureRandom.getInstanceStrong()daje mi NativePRNGBlockingalgorytm. Często blokowałoby się to na wiele sekund, aby wygenerować kilka bajtów soli.

NativePRNGNonBlockingZamiast tego przełączyłem się na wyraźne pytanie i zgodnie z oczekiwaniami po nazwie nie było już blokowane. Nie mam pojęcia, jakie są tego konsekwencje dla bezpieczeństwa. Prawdopodobnie wersja nieblokująca nie może zagwarantować ilości użytej entropii.

Aktualizacja : Ok, znalazłem to doskonałe wyjaśnienie .

Krótko mówiąc, aby uniknąć blokowania, użyj new SecureRandom(). To używa /dev/urandom, które nie blokuje i jest w zasadzie tak bezpieczne jak /dev/random. Z posta: „Jedyny przypadek, w którym chciałbyś wywołać / dev / random, to pierwszy rozruch maszyny, a entropia jeszcze się nie nagromadziła”.

SecureRandom.getInstanceStrong() daje absolutnie najsilniejszy RNG, ale można go bezpiecznie używać tylko w sytuacjach, w których kilka bloków nie wpłynie na ciebie.

Lachlan
źródło
1
Chciałbym tylko pozwalają getInstanceStrong() na długie klucze terminowych, takich jak te, dla certyfikatów TLS. I nawet wtedy wolałbym używać new SecureRandom()generatora par kluczy lub generatora liczb losowych zgodnego z FIPS. Więc tak, to daje odpowiedź, jeśli /dev/urandom nie blokuje: w końcu nadal opiera się na entropii systemu; ale ogólnie jest to bardzo dobra rada . Jeśli /dev/urandomblokuje, może być konieczne naprawienie źródła problemu, a nie aplikacji Java.
Maarten Bodewes
5

Istnieje narzędzie (przynajmniej na Ubuntu), które wprowadzi sztuczną losowość do twojego systemu. Polecenie to po prostu:

rngd -r /dev/urandom

i możesz potrzebować sudo z przodu. Jeśli nie masz pakietu rng-tools, musisz go zainstalować. Próbowałem tego i zdecydowanie mi pomogło!

Źródło: Matt vs World

David K.
źródło
2
Jest to nieco niebezpieczne, ponieważ całkowicie wyłącza szacowanie poziomu entropii jądra Linuksa w całym systemie. Myślę, że do celów testowych (czytaj: Jenkins uruchamia pakiet testowy aplikacji) użycie /dev/./urandom jest w porządku, ale w środowisku produkcyjnym tak nie jest.
mirabilos
To właściwie jedyne rozwiązanie, które mi się sprawdziło. Miałem problem z „niewystarczającą entropią” podczas tworzenia projektu na Androida z Gradle na Jenkins CI, a przekazanie parametru do kompilacji nie pomogło.
Slav
Musiałem połączyć się sudo rngd -r /dev/urandomz sudo apt install rng-toolsxenialem
MrMesees
5

Napotkałem ten sam problem . Po pewnym googlowaniu z odpowiednimi wyszukiwanymi hasłami natknąłem się na ten fajny artykuł na DigitalOcean .

Haveged to potencjalne rozwiązanie bez narażania bezpieczeństwa.

Cytuję tylko odpowiednią część z tego artykułu.

W oparciu o zasadę HAVEGE, a wcześniej w oparciu o powiązaną bibliotekę, haveged umożliwia generowanie losowości w oparciu o zmiany czasu wykonania kodu na procesorze. Ponieważ wykonanie jednego fragmentu kodu jest prawie niemożliwe, nawet w tym samym środowisku na tym samym sprzęcie, czas uruchomienia jednego lub wielu programów powinien być odpowiedni do zapoczątkowania losowego źródła. Nieudana implementacja wysiewa losowe źródło twojego systemu (zwykle / dev / random) przy użyciu różnic w liczniku znacznika czasu procesora (TSC) po wielokrotnym wykonaniu pętli

Jak zainstalować haveged

Wykonaj czynności opisane w tym artykule. https://www.digitalocean.com/community/tutorials/how-to-setup-additional-entropy-for-cloud-servers-using-haveged

Opublikowałem to tutaj

tak-przypadkowy-koleś
źródło
5

Problem, o którym się odwołujesz, /dev/randomnie dotyczy SecureRandomalgorytmu, ale źródła losowości, którego używa. Te dwa są ortogonalne. Powinieneś dowiedzieć się, który z nich spowalnia cię.

Niezbyt często strona Matematyka, do której odsyłasz, wyraźnie wspomina, że ​​nie dotyczą one źródła losowości.

Możesz wypróbować różnych dostawców JCE, takich jak BouncyCastle, aby sprawdzić, czy ich implementacja SecureRandomjest szybsza.

Krótkie wyszukiwanie ujawnia również łatki Linuksa, które zastępują domyślną implementację Fortuną. Nie wiem nic więcej na ten temat, ale zapraszam do zbadania.

Powinienem również wspomnieć, że chociaż bardzo niebezpieczne jest użycie źle zaimplementowanego SecureRandomalgorytmu i / lub źródła losowości, możesz utworzyć własnego dostawcę JCE z niestandardową implementacją SecureRandomSpi. Będziesz musiał przejść przez proces w firmie Sun, aby podpisać umowę z dostawcą, ale w rzeczywistości jest to całkiem proste; Wystarczy, że prześlesz im faksem formularz stwierdzający, że znasz amerykańskie ograniczenia eksportowe dotyczące bibliotek kryptograficznych.

ykaganovich
źródło
Ci różni dostawcy JCE są użyteczni tylko wtedy, gdy używają innego źródła entropii, co w zasadzie oznacza, że ​​muszą używać określonego sprzętu, takiego jak HSM. W przeciwnym razie są tak samo narażone na spowolnienia, w zależności od tego, ile entropii wydobywają z systemu.
Maarten Bodewes
3

Użyj bezpiecznego losowego jako źródła inicjalizacji dla powtarzającego się algorytmu; możesz wtedy użyć twistera Mersenne do pracy masowej zamiast tego w UncommonMath, który istnieje od jakiegoś czasu i okazał się lepszy niż inne prng

http://en.wikipedia.org/wiki/Mersenne_twister

Pamiętaj, aby od czasu do czasu odświeżyć bezpieczny losowy używany do inicjalizacji, na przykład możesz mieć jeden bezpieczny generowany losowo na klienta, używając jednego pseudo-losowego generatora twister mersenne na klienta, uzyskując wystarczająco wysoki stopień randomizacji

Lorenzo Boccaccia
źródło
2
Ta odpowiedź jest błędna: twister Mersenne nie jest bezpiecznym generatorem liczb losowych. Byłby to dobry algorytm dla Random, ale nie dla SecureRandom.
Maarten Bodewes
3

Zgodnie z dokumentacją różne algorytmy używane przez SecureRandom to, w kolejności preferencji:

  • W większości systemów * NIX
    1. NativePRNG
    2. SHA1PRNG
    3. NativePRNGBlocking
    4. NativePRNGNonBlocking
  • W systemach Windows
    1. SHA1PRNG
    2. Windows-PRNG

Ponieważ pytałeś o Linuksa, ignoruję implementację Windows, a także SunPKCS11, który jest naprawdę dostępny tylko w Solarisie, chyba że sam go zainstalowałeś - a wtedy nie pytałbyś o to.

Według tej samej dokumentacji, czego używają te algorytmy

SHA1PRNG
Wstępne udostępnianie jest obecnie wykonywane za pomocą kombinacji atrybutów systemowych i urządzenia gromadzącego entropię java.security.

NativePRNG
nextBytes() wykorzystuje /dev/urandom
generateSeed()zastosowań/dev/random

NativePRNGBlocking
nextBytes() i generateSeed()używanie/dev/random

NativePRNGNonBlocking
nextBytes() i generateSeed()używanie/dev/urandom

Oznacza to, że jeśli używasz SecureRandom random = new SecureRandom(), przegląda tę listę, dopóki nie znajdzie takiego, który działa, którym zazwyczaj będzie NativePRNG. A to oznacza, że ​​wysiewa się z /dev/random(lub używa tego, jeśli jawnie generujesz ziarno), a następnie używa /dev/urandomdo pobrania kolejnych bajtów, ints, double, booleans, what-have-you.

Ponieważ /dev/randomblokuje (blokuje, dopóki nie ma wystarczającej entropii w puli entropii), może to utrudnić działanie.

Jednym z rozwiązań jest użycie czegoś takiego jak haveged do wygenerowania wystarczającej entropii, a innym rozwiązaniem jest użycie /dev/urandomzamiast tego. Chociaż można to ustawić dla całej jvm, lepszym rozwiązaniem jest zrobienie tego dla tego konkretnego wystąpienia SecureRandom, używając SecureRandom random = SecureRandom.getInstance("NativePRNGNonBlocking"). Należy pamiętać, że ta metoda może zgłosić NoSuchAlgorithmException, jeśli NativePRNGNonBlocking, więc przygotuj się na powrót do wartości domyślnej.

SecureRandom random;
try {
    random = SecureRandom.getInstance("NativePRNGNonBlocking");
} catch (NoSuchAlgorithmException nsae) {
    random = new SecureRandom();
}

Zauważ również, że w innych systemach * nix /dev/urandommoże zachowywać się inaczej .


Czy jest /dev/urandomwystarczająco losowy?

Konwencjonalna mądrość mówi, że tylko /dev/randomjest wystarczająco przypadkowa. Jednak niektóre głosy się różnią. W „Właściwy sposób korzystania z SecureRandom” i „Mity o / dev / urandom” argumentowano, że /dev/urandom/jest to równie dobre.

Zgadzają się z tym użytkownicy na stosie bezpieczeństwa informacji . Zasadniczo, jeśli musisz o to zapytać, /dev/urandomjest w porządku.

SQB
źródło
2

Sam nie napotkałem tego problemu, ale przy starcie programu tworzyłem wątek, który natychmiast próbuje wygenerować ziarno, a następnie umiera. Metoda, którą wywołujesz dla randoms, dołączy do tego wątku, jeśli jest aktywny, więc pierwsze wywołanie blokuje się tylko wtedy, gdy występuje na bardzo wczesnym etapie wykonywania programu.

Nacięcie
źródło
To dość ekstremalny hack, ale może zadziałać; nie jest powiedziane, że użyty PRNG nie może używać dodatkowego materiału siewnego, który nadal mógłby prowadzić do zatykania. Zdecydowanie preferowane jest użycie innej liczby losowej zapewniającej lub ustalającej entropię w systemie. Ponieważ może to przynajmniej stanowić tymczasowe rozwiązanie, mimo wszystko zagłosowałem za odpowiedzią.
Maarten Bodewes
2

Moje doświadczenie dotyczyło tylko powolnej inicjalizacji PRNG, a nie późniejszego generowania losowych danych. Wypróbuj bardziej chętną strategię inicjalizacji. Ponieważ są drogie w tworzeniu, traktuj je jak pojedyncze egzemplarze i używaj ponownie tej samej instancji. Jeśli w jednym wystąpieniu występuje zbyt duża rywalizacja o wątki, połącz je lub ustaw jako lokalne wątki.

Nie idź na kompromis przy generowaniu liczb losowych. Słabość w tym miejscu naraża całe twoje bezpieczeństwo.

Nie widzę wielu generatorów COTS opartych na rozpadzie atomowym, ale istnieje kilka planów dla nich, jeśli naprawdę potrzebujesz wielu losowych danych. Jedną z witryn, które zawsze zawierają interesujące rzeczy do obejrzenia, w tym HotBits, jest Fourmilab Johna Walkera.

erickson
źródło
1
Zawsze się nad tym zastanawiałem, ponieważ produkty hadronowego rozpadu tau prawie osiągają ideał losowego źródła, po prostu nie mogę pozbyć się chęci używania tego, a nie narzędzi algorytmicznych. Dla celów OP, już dawno temu zdecydowałem, że czas na front-end jest endemiczny dla wszystkich bezpiecznych narzędzi. Jeśli ktoś będzie potrzebował randomizera, który można wywołać w konstruktorze i po prostu pamiętać o skonstruowaniu go w czasie ładowania strony, jest on ukryty pod wymianą avl i nawet tak wybredny jak ja pozostaje niezauważony.
Nicholas Jordan
Chipsety Intel 8xx (i prawdopodobnie wiele innych) mają sprzętowy RNG, który wykorzystuje szum termiczny, naprawdę nieprzewidywalny efekt kwantowy. Moduły zaufanej platformy mogą również zawierać sprzętowe RNG, ale niestety ten w moim laptopie nie.
erickson
Zależy to od konkretnego RNG, czy zasieje raz, czy ponownie zasieje po pewnym czasie. NIST określa PRNG, które są ponownie osadzane, ale wiele implementacji oprogramowania tego nie robi. Restrukturyzacja kodu wokół singletona to okropny pomysł, szczególnie w przypadku implementacji wielowątkowych; lepiej jest naprawić źródło problemu: powolne wysiewanie z powodu braku entropii. Jeśli używasz singletona, użyj go, aby zapewnić nasiona dla innych implementacji SecureRandom, które są całkowicie deterministyczne. Ten rodzaj projektowania wymaga jednak pewnej wiedzy.
Maarten Bodewes
@MaartenBodewes To są dobre strony. Jeśli implementacja blokuje, czekając na entropię systemu, myślę, że traktowanie jej jako singletona w twojej aplikacji nie jest okropnym pomysłem, ponieważ bazowe źródło jest w rzeczywistości singletonem. Ale użycie tej jednej instancji do zasiania innych jest dobrą sugestią, nawet jeśli jest złożona. Nie jestem pewien, ale myślę, że dostawca Słońca (a następnie Oracle) SecureRandomzmienił się kilka razy w ciągu ostatnich 10 lat w gromadzeniu entropii.
erickson,
Jestem bardzo pewien, że zmieniło się to całkiem sporo, na tyle, że nie będę się starał umieszczać wszystkich zmian w tym komentarzu :). Jest mniej prawdopodobne, że powolność SecureRandomjest nadal problemem, ale niska entropia w systemie zawsze będzie problemem. Użycie singletona spowoduje utworzenie silnie sprzężonego kodu, który jest wzorcem projektowym. Dlatego należy go używać z najwyższą ostrożnością; najlepiej byłoby odwrócić wszystkie odwołania w kodzie, jeśli chcesz rozwiązać problem.
Maarten Bodewes
2

Wygląda na to, że powinieneś jaśniej określić swoje wymagania dotyczące RNG. Najsilniejszym wymaganiem kryptograficznym RNG (jak rozumiem) byłoby to, że nawet jeśli znasz algorytm używany do ich generowania i znasz wszystkie wcześniej wygenerowane liczby losowe, nie możesz uzyskać żadnych przydatnych informacji o żadnej z liczb losowych wygenerowanych w przyszłości, bez wydawania niepraktycznej ilości mocy obliczeniowej.

Jeśli nie potrzebujesz tej pełnej gwarancji losowości, prawdopodobnie istnieją odpowiednie kompromisy dotyczące wydajności. Zgodziłbym się z odpowiedzią Dana Dyera na temat AESCounterRNG z Uncommons-Maths lub Fortuna (jednym z jej autorów jest Bruce Schneier, ekspert w dziedzinie kryptografii). Ja też nigdy nie korzystałem, ale na pierwszy rzut oka pomysły wydają się godne zaufania.

Pomyślałbym , że gdybyś mógł okresowo generować początkowe losowe ziarno (np. Raz dziennie, godzinę lub cokolwiek innego), mógłbyś użyć szybkiego szyfru strumieniowego do generowania liczb losowych z kolejnych fragmentów strumienia (jeśli szyfr strumieniowy używa XOR, to po prostu przekazać strumień wartości null lub bezpośrednio pobrać bity XOR). EStream firmy ECRYPTProjekt zawiera wiele dobrych informacji, w tym testy wydajności. Nie utrzymałoby to entropii między punktami w czasie, w których ją uzupełniasz, więc gdyby ktoś znał jedną z liczb losowych i algorytm, którego użyłeś, technicznie byłoby możliwe, z dużą mocą obliczeniową, złamać szyfr strumieniowy i zgadnij jego stan wewnętrzny, aby móc przewidzieć przyszłe liczby losowe. Ale musiałbyś zdecydować, czy to ryzyko i jego konsekwencje są wystarczające, aby uzasadnić koszt utrzymania entropii.

Edycja: oto kilka notatek z kursu kryptograficznego na temat RNG , które znalazłem w sieci, które wyglądają bardzo na ten temat.

Jason S.
źródło
1
„Fortuna (jednym z jej autorów jest Bruce Schneier, ekspert w dziedzinie kryptografii)” - a drugim Niels Ferguson, ekspert w dziedzinie kryptografii :-)
Steve Jessop
2

Jeśli twój sprzęt to obsługuje, spróbuj użyć narzędzia Java RdRand, którego jestem autorem.

Jest oparty na RDRANDinstrukcjach Intela i jest około 10 razy szybszy niż SecureRandomi nie ma problemów z przepustowością w przypadku implementacji dużej objętości.


Zauważ, że ta implementacja działa tylko na tych procesorach, które dostarczają instrukcje (tj. Gdy rdrandflaga procesora jest ustawiona). Musisz jawnie utworzyć instancję za pomocą RdRandRandom()konstruktora; żaden konkretny Providernie został wdrożony.

user2781824
źródło
3
Możesz przeczytać people.umass.edu/gbecker/BeckerChes13.pdf i nigdy nie używać wyłącznie danych Intel RDRAND. Zawsze mieszaj to z innymi nieprzewidywalnymi danymi, takimi jak wyjście szyfru strumieniowego aRC4 (zaszczepione z / dev / urandom i z kilkoma pierwszymi KiB wyjściowymi wyrzuconymi ze względu na ich znane odchylenie).
mirabilos
+1 mirabilos. Myślę, że RDRANDto dobre źródło, ale trochę niegodne zaufania. Zdecydowanie musi to być jeden z wielu wkładów do kolekcjonera (bez obrazy Davida Johnstona).
jww
Zagłosowałem za, poprawiłem link i podałem kilka podstawowych informacji. Jeśli nie zgadzasz się, cofnij zmianę.
Maarten Bodewes
1

Inną kwestią, na którą należy zwrócić uwagę, jest właściwość securerandom.source w pliku lib / security / java.security

Używanie / dev / urandom zamiast / dev / random może przynieść korzyści w zakresie wydajności. Pamiętaj, że jeśli jakość liczb losowych jest ważna, nie idź na kompromis, który łamie zabezpieczenia.

Diastrofizm
źródło