it-swarm.com.de

Wie erstelle ich einen sicheren zufälligen AES-Schlüssel in Java?

Was ist die empfohlene Methode zum Generieren eines sicheren, zufälligen AES-Schlüssels in Java mit dem Standard-JDK?

In anderen Beiträgen habe ich dies gefunden, aber die Verwendung von SecretKeyFactory könnte eine bessere Idee sein:

KeyGenerator keyGen = KeyGenerator.getInstance("AES");
SecureRandom random = new SecureRandom(); // cryptograph. secure random 
keyGen.init(random); 
SecretKey secretKey = keyGen.generateKey();

Es wäre großartig, wenn die Antwort eine Erklärung enthalten würde, warum dies ein guter Weg ist, den Zufallsschlüssel zu generieren. Vielen Dank!

50
barfuin

Ich würde Ihren vorgeschlagenen Code verwenden, aber mit einer leichten Vereinfachung:

KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(256); // for example
SecretKey secretKey = keyGen.generateKey();

Lassen Sie den Anbieter auswählen, wie er die Zufälligkeit erhalten möchte. Definieren Sie nichts, das möglicherweise nicht so gut ist wie das, was der Anbieter bereits ausgewählt hat.

In diesem Codebeispiel wird davon ausgegangen ( wie Maarten weiter unten ausführt ), dass Sie Ihre Java.security - Datei so konfiguriert haben, dass Ihr bevorzugter Anbieter ganz oben auf der Liste steht. Wenn Sie den Anbieter manuell angeben möchten, rufen Sie einfach KeyGenerator.getInstance("AES", "providerName"); auf.

Für einen wirklich sicheren Schlüssel müssen Sie ein Hardware-Sicherheitsmodul (HSM) verwenden, um den Schlüssel zu generieren und zu schützen. HSM-Hersteller stellen in der Regel einen JCE-Anbieter zur Verfügung, der die gesamte Schlüsselgenerierung mit dem obigen Code für Sie ausführt.

73
Duncan Jones

Die bevorzugte Methode wäre KeyGenerator. Wie Duncan angedeutet hat, würde ich die Schlüsselgröße bei der Initialisierung mit Sicherheit angeben. KeyFactory ist eine Methode, die für bereits vorhandene Schlüssel verwendet werden sollte.

OK, also kommen wir zur Sache. Grundsätzlich können AES-Schlüssel einen beliebigen Wert haben. Es gibt keine "schwachen Schlüssel" wie in (3) DES. Es gibt auch keine Bits mit einer bestimmten Bedeutung wie in (3) DES-Paritätsbits. Das Generieren eines Schlüssels kann also so einfach sein, als ob Sie ein Byte-Array mit zufälligen Werten generieren und ein SecretKeySpec darum erstellen.

Die Methode, die Sie verwenden, bietet jedoch noch einige Vorteile: Die KeyGenerator wird speziell zum Generieren von Schlüsseln erstellt. Dies bedeutet, dass der Code für diese Generation optimiert werden kann. Dies könnte Effizienz- und Sicherheitsvorteile haben. Es könnte so programmiert sein, dass Angriffe auf einen zeitseitigen Kanal vermieden werden, die beispielsweise den Schlüssel offen legen würden. Beachten Sie, dass es möglicherweise bereits eine gute Idee ist, byte[], die wichtige Informationen enthalten, da diese möglicherweise in eine Auslagerungsdatei gelangen (dies kann jedoch trotzdem der Fall sein).

Darüber hinaus verwenden, wie gesagt, nicht alle Algorithmen vollständig zufällige Schlüssel. Die Verwendung von KeyGenerator würde den Wechsel zu anderen Algorithmen erleichtern. Neuere Chiffren akzeptieren jedoch nur völlig zufällige Schlüssel. dies wird als ein Hauptvorteil gegenüber z.B. DES.

Schließlich und in meinem Fall der wichtigste Grund dafür, dass die KeyGenerator -Methode die einzig gültige Methode zum Behandeln von AES-Schlüsseln innerhalb eines sicheren Tokens (Smartcard, TPM, USB-Token oder HSM) ist. Wenn Sie das byte[] mit dem SecretKeySpec dann kommt der Schlüssel muss aus dem Speicher. Das bedeutet, dass der Schlüssel möglicherweise im sicheren Token abgelegt wird, der Schlüssel jedoch trotzdem im Speicher verfügbar ist. Normalerweise funktionieren sichere Token nur mit Schlüsseln, die entweder im sicheren Token generiert oder von z. eine Chipkarte oder eine Schlüsselzeremonie. Ein KeyGenerator kann mit einem Provider geliefert werden, so dass der Schlüssel direkt innerhalb des sicheren Tokens generiert wird.

Wie in Duncans Antwort angegeben: Geben Sie immer die Schlüsselgröße (und alle anderen Parameter) explizit an. Verlassen Sie sich nicht auf die Standardeinstellungen des Anbieters, da dies wird es unklar macht, was Ihre Anwendung tut, und jeder Anbieter möglicherweise seine eigenen Standardeinstellungen hat.

23
Maarten Bodewes

Viele gute Tipps in den anderen Beiträgen. Das benutze ich:

Key key;
SecureRandom Rand = new SecureRandom();
KeyGenerator generator = KeyGenerator.getInstance("AES");
generator.init(256, Rand);
key = generator.generateKey();

Wenn Sie einen anderen Zufallsanbieter benötigen, den ich manchmal zu Testzwecken verwende, ersetzen Sie einfach Rand durch

MySecureRandom Rand = new MySecureRandom();
4
Andy