Le thread SecureRandom est-il sûr?

103

Le SecureRandomthread est-il sûr? Autrement dit, après l'initialisation, l'accès au prochain nombre aléatoire peut-il être fiable pour être thread-safe? L'examen du code source semble montrer que c'est le cas, et ce rapport de bogue semble indiquer que son manque de documentation en tant que thread safe est un problème javadoc. Quelqu'un a-t-il confirmé qu'il était en fait thread-safe?

Yishai
la source

Réponses:

108

Oui, ça l'est. Il s'étend Random, qui a toujours eu une implémentation de facto threadsafe, et, de Java 7, garantit explicitement la sécurité des threads.

Si de nombreux threads utilisent un seul SecureRandom, il peut y avoir des conflits qui nuisent aux performances. D'un autre côté, l'initialisation d'une SecureRandominstance peut être relativement lente. Il est préférable de partager un RNG global ou d'en créer un nouveau pour chaque thread dépendra de votre application. La ThreadLocalRandomclasse peut être utilisée comme modèle pour fournir une solution prenant en charge SecureRandom.

Erickson
la source
3
Merci pour la mise à jour. Curieusement, le bogue est marqué comme fermé comme "ne résoudra pas". Mais ils l'ont quand même réparé. Eh bien, je ne leur envie pas la taille de leur base de données de bogues.
Yishai le
4
l'initialisation d'un SecureRandompeut non seulement être lente, mais peut potentiellement se bloquer en raison d'une entropie manquante
Walter Tross
8
Veuillez garder à l'esprit que ThreadLocalRandom est très facile à craquer, donc si vous prévoyez d'exposer la valeur générée au monde, utilisez plutôt SecureRandom jazzy.id.au/default/2010/09/20/…
walv
2
Je vais m'éclipser ici et dire que cette réponse est incorrecte. Le contrat pour Random, qui garantit la sécurité des threads, ne lie pas les sous-classes. Certes, toutes les autres propriétés de Random documentées ne sont pas contraignantes pour les sous-classes, donc je ne vois pas pourquoi la sécurité des threads devrait être supposée.
Président James K. Polk
2
@JamesKPolk Ne pas conserver une propriété du supertype violerait le principe de substituabilité.
erickson
11

L'implémentation actuelle de SecureRandomest thread-safe, en particulier les deux méthodes de mutation nextBytes(bytes[])et setSeed(byte[])sont synchronisées.

Eh bien, pour autant que j'ai pu le dire, toutes les méthodes de mutation sont finalement acheminées via ces deux méthodes, et SecureRandomremplacent quelques méthodes Randompour garantir cela. Ce qui fonctionne mais pourrait être fragile si la mise en œuvre est modifiée à l'avenir.

La meilleure solution consiste à effectuer d'abord une synchronisation manuelle sur l' SecureRandominstance. Cela signifie que chaque pile d'appels acquiert deux verrous sur le même objet, mais c'est généralement très bon marché sur les JVM modernes. Autrement dit, il n'y a pas beaucoup de mal à se synchroniser explicitement. Par exemple:

    SecureRandom rnd = ...;

    byte[] b = new byte[NRANDOM_BYTES];
    synchronized (rnd) {
        rnd.nextBytes(b);
    }
Matt Quail
la source
3
Au moins dans JDK 10, SecureRandom est basé sur un fournisseur et vérifie si le fournisseur est thread-safe, ne se synchronisant que si ce n'est pas le cas, dans nextBytes.
nafg le
java.security.SecureRandom#nextBytesdans Java 8 n'est pas synchronisé. Pouvez-vous préciser dans quelle version Java avez-vous trouvé un synchronisé #nextBytes?.
Jaime Hablutzel