2017-03-13 1 views
3

Durch das Forum lesen, scheint es, dass die SecureRandom Thread sicher ist, aber es in Multi-Threaded-Systemen wegen Konkurrenz zu kämpfen, siehe Is SecureRandom thread safe? . Auch die Initialisierung eines neuen SecureRandom ist eine teure Operation. Ein Vorschlag zur Verbesserung der Leistung ist die Verwendung von ThreadLocalRandom.SecureRandom: Thread sicher ohne Konkurrenz und immer noch kryptographisch sicher?

Also änderte ich meinen Code aus:

SecureRandom randomSecureRandom = SecureRandom.getInstance("SHA1PRNG"); 

zu:

private final ThreadLocalRandom randomThreadLocal = ThreadLocalRandom.current(); 

ich einige Tests haben - 100 Läufe für 10000 String-Werte zu verschlüsseln, und ich kann deutliche Verbesserung sehen.

**With ThreadLocalRandom** 
Thread #18New encryption service took on average: 66.44ms. 
Thread #17New encryption service took on average: 64.79ms. 
Thread #14New encryption service took on average: 70.77ms. 
Thread #13New encryption service took on average: 72.33ms. 
Thread #19New encryption service took on average: 73.42ms. 
Thread #15New encryption service took on average: 74.21ms. 
Thread #11New encryption service took on average: 76.79ms. 
Thread #16New encryption service took on average: 78.72ms. 
Thread #12New encryption service took on average: 78.95ms. 
Thread #20New encryption service took on average: 78.99ms. 

**With SecureRandom** 
Thread #19New encryption service took on average: 87.26ms. 
Thread #18New encryption service took on average: 93.65ms. 
Thread #13New encryption service took on average: 93.1ms. 
Thread #15New encryption service took on average: 95.81ms. 
Thread #16New encryption service took on average: 96.9ms. 
Thread #11New encryption service took on average: 97.0ms. 
Thread #20New encryption service took on average: 94.93ms. 
Thread #17New encryption service took on average: 96.63ms. 
Thread #12New encryption service took on average: 97.41ms. 
Thread #14New encryption service took on average: 99.08ms. 

Es scheint, dass ich auf jeden Fall die Geschwindigkeit hier verbessert, jedoch verschlechtert ich die Sicherheit, weil es die ThreadLocalRandom scheint nicht kryptographisch sicher:

* <p>Instances of {@code ThreadLocalRandom} are not cryptographically 
* secure. Consider instead using {@link java.security.SecureRandom} 
* in security-sensitive applications 

Meine Frage ist - ist es eine Möglichkeit, kryptographisch sicher zu schaffen Zufallszahl, die threadsicher ist und in einem Multithread-System gut funktioniert?

Es gibt eine weitere Frage zu diesem Thema zu berühren, aber die Antwort darauf hindeutet, den gleichen Übergang von SecureRandom ->ThreadLocalRandom, die sehen Minimizing SecureRandom performance problems in multithreaded environment? nicht kryptografisch sicher ist.

+1

Wie viele Threads müssen die zufällige verwenden? Ich weiß, dass Sie gesagt haben, dass das Erstellen eines 'SecureRandom' teuer ist. Dennoch möchten Sie vielleicht messen, ob das Erstellen eines einzelnen Threads am Ende ein schnelleres Ergebnis liefert, weil es keine Konkurrenz gibt. –

+0

Es gibt andere Möglichkeiten, Zufallswerte zu generieren, d.Durch die Verwendung von Hardware, das Hören des Geräuschhintergrunds eines Mikrofons oder die Verwendung eines externen Magnetometers kann man auch zufällige Daten aus dem Internet herunterladen, jedoch ist es sehr unwahrscheinlich, dass diese Methoden in einer Multithread-Umgebung schneller und effektiver sind. Ich schlage vor, bei "SecureRandom" zu bleiben und sicherzustellen, dass Sie dieselbe Instanzinstanz unter mehreren Threads wiederverwenden und einfach die '.nextBytes (..)' Funktion aufrufen. Am Ende, wenn Sie kryptografisch starke Werte wollen, müssen Sie dafür Leistung zahlen. – cristianhh

+0

Sie haben also ungefähr 30 ms pro Anruf gespeichert. Das ist kaum eine große Veränderung, wird das in der Gesamtleistung von Bedeutung sein? Möchten Sie sichere Zufallszahlen oder nur Zufallszahlen? – john16384

Antwort

3

SecureRandom Implementierung ist viel langsamer als ThreadLocalRandom. Dies steht nicht im Zusammenhang mit der Thread-Sicherheit.

ThreadLocalRandom Der Algorithmus zur Generierung der nächsten Zufallszahl erfordert nur sehr wenige mathematische Operationen und ist leicht zu knacken. Tatsächlich ist das von einer einzigen nextLong-Operation zurückgegebene Ergebnis ausreichend, um alle von diesem Generator generierten zukünftigen und vergangenen Zahlen zu ermitteln, siehe https://jazzy.id.au/2010/09/20/cracking_random_number_generators_part_1.html, wenn Sie an Details interessiert sind.

Auf der anderen Seite verwendet SecureRandom mit dem ausgewählten Anbieter SHA1 zum Generieren von Zufallszahlen. SHA1 ist rechenintensiv, so dass die Leistung schlechter ist als die von ThreadLocalRandom. Das ist Absicht - Rechenkomplexität ist einer der Faktoren, die SHA1 schwer rückgängig machen können, und der Keim ist schwer zu erraten.

Um die Leistung zu vergleichen, habe ich 100M Zufallszahlen in einem einzigen Thread mit beiden Generatoren generiert. ThreadLocalRandom dauerte 95ms, SecureRandom dauerte 41 Sekunden.

EDIT Threading Leistung Adresse:

Sie eine SecureRandom Instanz für jeden Thread erstellen können. Es wird bei der ersten Verwendung mit Daten initialisiert, die aus einer statischen (gemeinsam genutzten/synchronisierten) Instanz stammen. Nachfolgende Operationen werden jedoch Thread-lokal ausgeführt. Ich habe die Leistung von 4 Threads mit Shared vs dedizierten SecureRandom Instanz gemessen. Jeder Thread erzeugte 100 Millionen Zufallszahlen; dedizierte Instanz dauerte 30 Sekunden, geteilt dauerte 1 min 54 sec.

+0

Ich glaube, Joan Boyer hat als erster veröffentlicht, wie man eine LCG bricht. Später zeigte sie, wie man eine LCG bricht, die Bits verworfen hat. Siehe auch [Inferring-Sequenzen, die vom Pseudozufallszahlengenerator erzeugt werden] (http://asterix.cs.gsu.edu/crypto/p129-boyar.pdf). – jww