2011-01-13 4 views
1

Ich habe einige Arbeit mit Javas SecureRandom-Klasse gemacht, um Salze für die spätere Verschlüsselung und Kennwort Hashing zu generieren (ich erzeuge separate Salze für jede Aufgabe). Der Code, den ich verwendet habe, ist wie folgt:Java und kryptografisch starke Zufallszahlen

//Init random number generator 
secureRandom = SecureRandom.getInstance("SHA1PRNG"); 
secureRandom.setSeed(System.nanoTime()); 

//Create salts 
secureRandom.nextBytes(bytAuthSalt); 
secureRandom.nextBytes(bytEncryptionSalt); 

Nun, alles ging gut, bis ich tatsächlich begonnen, um die Werte zu überprüfen, die ich habe. Für mehrere aufeinanderfolgende Ausführungen der Anwendung meine Salze waren:

[[email protected] 
[[email protected] 
[[email protected] 
[[email protected] 
[[email protected] 
[[email protected] 

ich durch die Tatsache gestört bin, dass die Zahlen alle erscheinen grob sequenziellen sein. Nach einigem Suchen im Web, wiederholte ich die Läufe erneut, ohne sie selbst zu den gleichen Ergebnissen zu bringen.

Meine einzige Vermutung darüber, was dies verursacht, kommt von der Tatsache, dass ich für die Android-Plattform entwickle. Ich weiß, dass sie ihre eigenen kryptografischen Anbieter haben, aber ich bekomme keine Ausnahmen. irgendwelche Ideen?

Vielen Dank im Voraus.

Antwort

9

Es sieht so aus, als ob Sie den Verweis auf das Byte-Array anstelle des Inhalts drucken. Aus diesem Grund sind sie sequenziell, die Referenz gibt Ihnen den Speicherort im JVM-Speicher. Konvertieren Sie das Byte-Array in einen String, bevor Sie es drucken.

String saltContents = Arrays.toString(bytAuthSalt); 

Konvertieren des Array in einen String Arrays Verwendung finden Sie die Rohwerte der Bytes zeigen.

+3

Wenn ich mich nicht irre, wird das die Bytes mit dem Standard-Zeichensatz interpretieren, anstatt rohe Bytes auszudrucken. Will das OP nicht die rohen Bytes und nicht die ASCII-äquivalenten Zeichen? –

+1

@ RD01 - Aber immer noch, es wird OP eine gute Sicht auf Werte Zufälligkeit geben. – Rogach

+2

@rogach Ich stimme zu, aber viele dieser Werte werden als Ctrl-Zeichen oder Leerzeichen angezeigt, so dass Sie nicht alle Bytes auswerten können. –

4

Scheint, dass Sie ein Array drucken, keine tatsächlichen Werte. "[B @" sagt Ihnen, dass es sich um ein Byte-Array und alles nach der Objekt-ID handelt.
versuchen, etwas wie folgt aus:

System.out.println("bytAuthSalt"); 
    for (byte b : bytAuthSalt) { 
    System.out.print(b); 
    } 
    System.out.println(); 

Oder diese:

Arrays.toString(bytAuthSalt); 

Diese werden alle Werte im Array drucken.

+3

oder Arrays.toString (byte []) –

+0

Oh, danke! Wusste das nicht. – Rogach

+0

Das Bit über "[B @", das die Signatur für ein Byte-Array ist, nicht bekannt war. – phobos51594

1

Ich würde auch empfehlen, nicht für Seeding System.nanoTime() zu verwenden, da es nicht garantiert, auf allen Plattformen ordnungsgemäß zu funktionieren. In einigen Fällen gibt es nur "Null" zurück, was ich denke, dass es keine richtige Zahl für das Aussäen von RNG ist.

2

SHA1PRNG ist nur so sicher wie sein Seed. Aus diesem Grund ist die Verwendung von System.nanoTime() als Seed eine schreckliche Idee. Angreifer, der den Zeitbereich des Seeding ausreichend eingrenzen kann, kann alle möglichen Werte ausprobieren, bis er die passende Sequenz gefunden hat. Der Angreifer wird durch die Tatsache unterstützt, dass die Auflösung von System.nanoTime() normalerweise viel größer als 1 Nanosekunde ist.

Es ist viel besser, einfach new SecureRandom() zu tun, damit JRE die bestmögliche Implementierung auswählen kann. Auf den meisten Plattformen würde dies die OS-native Entropiequelle verwenden, um RNG zu erzeugen, wie /dev/random.