Czy wątek SecureRandom jest bezpieczny?

103

Czy SecureRandomwątek jest bezpieczny? To znaczy, czy po jego zainicjowaniu można polegać na dostępie do następnej liczby losowej, aby był bezpieczny dla wątków? Badanie kodu źródłowego wydaje się wskazywać, że tak jest, a ten raport o błędzie wydaje się wskazywać, że brak dokumentacji jako bezpiecznej dla wątków jest problemem javadoc. Czy ktoś potwierdził, że faktycznie jest bezpieczny wątkowo?

Yishai
źródło

Odpowiedzi:

108

Tak to jest. Rozszerza Random, który zawsze miał de facto implementację ochrony wątków, a od Java 7 wyraźnie gwarantuje bezpieczeństwo wątków.

Jeśli wiele wątków używa jednego SecureRandom, może dojść do sporu, który obniża wydajność. Z drugiej strony inicjowanie SecureRandominstancji może być stosunkowo powolne. To, czy najlepiej udostępnić globalną RNG, czy też utworzyć nową dla każdego wątku, zależy od aplikacji. ThreadLocalRandomKlasy można stosować jako wzorzec do uzyskania roztworu, który obsługuje SecureRandom.

erickson
źródło
3
Dziękuję za aktualizację. Co dziwne, błąd jest oznaczony jako zamknięty jako „nie zostanie naprawiony”. Ale i tak to naprawili. No cóż, nie zazdroszczę im rozmiaru ich bazy danych błędów.
Yishai
4
inicjalizacja a SecureRandommoże nie tylko być powolna, ale może potencjalnie zawiesić się z powodu brakującej entropii
Walter Tross,
8
Należy pamiętać, że ThreadLocalRandom jest bardzo łatwy do złamania, więc jeśli planujesz ujawnić światu wygenerowaną wartość, użyj SecureRandom zamiast jazzy.id.au/default/2010/09/20/ ...
walv
2
Mam zamiar wyjść na nogę i powiedzieć, że ta odpowiedź jest nieprawidłowa. Umowa na Random, która gwarantuje bezpieczeństwo wątków, nie jest wiążąca dla podklas. Z pewnością wszystkie inne udokumentowane właściwości Random nie są wiążące dla podklas, więc nie rozumiem, dlaczego należy zakładać bezpieczeństwo wątków.
Prezydent James K. Polk
2
@JamesKPolk Niezachowanie właściwości nadtypu naruszyłoby zasadę zastępowalności.
erickson
11

Obecna implementacja SecureRandomjest bezpieczna dla wątków, w szczególności dwie metody mutowania nextBytes(bytes[])i setSeed(byte[])są zsynchronizowane.

O ile mogłem stwierdzić, wszystkie metody mutowania są ostatecznie kierowane przez te dwie metody i SecureRandomzastępują kilka metod, Randomaby to zapewnić. Co działa, ale może być kruche, jeśli implementacja zostanie zmieniona w przyszłości.

Najlepszym rozwiązaniem jest SecureRandomnajpierw ręczna synchronizacja na instancji. Oznacza to, że każdy stos wywołań uzyska dwie blokady na tym samym obiekcie, ale jest to zwykle bardzo tanie w nowoczesnych maszynach JVM. Oznacza to, że jawna synchronizacja się nie szkodzi. Na przykład:

    SecureRandom rnd = ...;

    byte[] b = new byte[NRANDOM_BYTES];
    synchronized (rnd) {
        rnd.nextBytes(b);
    }
Matt Quail
źródło
3
Przynajmniej w JDK 10 SecureRandom opiera się na dostawcy i sprawdza, czy dostawca jest bezpieczny wątkowo, synchronizując tylko, jeśli nie jest, w nextBytes.
nafg
java.security.SecureRandom#nextBytesw Javie 8 nie jest zsynchronizowany. Czy możesz określić, w której wersji Java znalazłeś zsynchronizowany plik #nextBytes?
Jaime Hablutzel