Ich muss eine 256-Bit-AES-Verschlüsselung implementieren, aber alle Beispiele, die ich online gefunden habe, verwenden einen "KeyGenerator", um einen 256-Bit-Schlüssel zu generieren, aber ich möchte meinen eigenen Passkey verwenden. Wie kann ich meinen eigenen Schlüssel erstellen? Ich habe versucht, es auf 256 Bit aufzufüllen, aber dann erhalte ich eine Fehlermeldung, dass der Schlüssel zu lang ist. Ich habe den Unlimited Jurisdiction Patch installiert, das ist also nicht das Problem :)
Dh. Der KeyGenerator sieht so aus ...
// Get the KeyGenerator
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128); // 192 and 256 bits may not be available
// Generate the secret key specs.
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
BEARBEITEN
Ich habe das Passwort tatsächlich auf 256 Bytes aufgefüllt, nicht auf Bits, was zu lang ist. Das Folgende ist ein Code, den ich jetzt verwende, da ich mehr Erfahrung damit habe.
byte[] key = null; // TODO
byte[] input = null; // TODO
byte[] output = null;
SecretKeySpec keySpec = null;
keySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
cipher.init(Cipher.ENCRYPT_MODE, keySpec);
output = cipher.doFinal(input)
Die "TODO" -Bits, die du selbst machen musst :-)
quelle
Antworten:
Teilen Sie die
password
(achar[]
) undsalt
(a -byte[]
8 Bytes, die von a ausgewählt wurden, um einSecureRandom
gutes Salz zu erhalten - das nicht geheim gehalten werden muss) mit dem Empfänger außerhalb des Bandes. Um dann aus diesen Informationen einen guten Schlüssel abzuleiten:Die magischen Zahlen (die irgendwo als Konstanten definiert werden könnten) 65536 und 256 sind die Anzahl der Schlüsselableitungsiterationen bzw. die Schlüsselgröße.
Die Schlüsselableitungsfunktion wird iteriert, um einen erheblichen Rechenaufwand zu erfordern. Dies verhindert, dass Angreifer schnell viele verschiedene Kennwörter ausprobieren können. Die Anzahl der Iterationen kann abhängig von den verfügbaren Rechenressourcen geändert werden.
Die Schlüsselgröße kann auf 128 Bit reduziert werden, was immer noch als "starke" Verschlüsselung angesehen wird, aber es gibt keinen großen Sicherheitsspielraum, wenn Angriffe entdeckt werden, die AES schwächen.
Bei Verwendung eines geeigneten Blockverkettungsmodus kann derselbe abgeleitete Schlüssel zum Verschlüsseln vieler Nachrichten verwendet werden. Bei der Verschlüsselungsblockverkettung (CBC) wird für jede Nachricht ein zufälliger Initialisierungsvektor (IV) erzeugt, der einen anderen Verschlüsselungstext ergibt, selbst wenn der Klartext identisch ist. CBC ist möglicherweise nicht der sicherste Modus, der Ihnen zur Verfügung steht (siehe AEAD unten). Es gibt viele andere Modi mit unterschiedlichen Sicherheitseigenschaften, aber alle verwenden eine ähnliche zufällige Eingabe. In jedem Fall sind die Ausgaben jeder Verschlüsselungsoperation der Chiffretext und der Initialisierungsvektor:
Speichern Sie die
ciphertext
und dieiv
. Bei der Entschlüsselung wird dasSecretKey
auf genau die gleiche Weise neu generiert, wobei das Kennwort mit denselben Salt- und Iterationsparametern verwendet wird. Initialisieren Sie die Verschlüsselung mit diesem Schlüssel und den mit der Nachricht gespeicherten Initialisierungsvektor:Java 7 enthielt API- Unterstützung für AEAD-Verschlüsselungsmodi , und der in OpenJDK- und Oracle-Distributionen enthaltene "SunJCE" -Anbieter implementiert diese ab Java 8. Einer dieser Modi wird dringend anstelle von CBC empfohlen. Es schützt die Integrität der Daten sowie deren Privatsphäre.
A
java.security.InvalidKeyException
mit der Meldung „Unzulässige Tastengröße oder Standardparameter“ bedeutet , dass die Kryptografie - Stärke ist begrenzt; Die Richtliniendateien mit unbegrenzter Stärke befinden sich nicht am richtigen Speicherort. In einem JDK sollten sie unter platziert werden${jdk}/jre/lib/security
Basierend auf der Problembeschreibung scheint es, dass die Richtliniendateien nicht korrekt installiert sind. Systeme können problemlos mehrere Java-Laufzeiten haben. Stellen Sie sicher, dass der richtige Speicherort verwendet wird.
quelle
PBEwith<prf>and<encryption>
Algorithmen nicht gut . Zum Beispiel bietet SunJCE kein PBE für AES. Zweitens ist das Aktivieren von Jasypt kein Ziel. Ein Paket, das angeblich Sicherheit bietet, ohne die zugrunde liegenden Prinzipien zu verstehen, scheint auf den ersten Blick gefährlich.tmp.getEncoded()
als Hash speichern würden . Sie sollten auch diesalt
und die Iterationen (in diesem Beispiel 65536) speichern , damit Sie den Hash neu berechnen können, wenn jemand versucht, sich zu authentifizieren. In diesem Fall generieren Sie das Salz bei jeder Änderung des Kennworts mit einem kryptografischen Zufallszahlengenerator.Erwägen Sie die Verwendung des Spring Security Crypto-Moduls
Es bietet eine einfache Abstraktion für die Verschlüsselung und scheint mit den hier erforderlichen Anforderungen übereinzustimmen.
Ein Blick auf die Einbauten zeigt eine Struktur ähnlich der von Erickson .
Wie in der Frage erwähnt, erfordert dies auch die JCE-Richtlinie ( Unlimited Strength Jurisdiction Policy) für Java Cryptography Extension (andernfalls
InvalidKeyException: Illegal Key Size
). Es kann für Java 6 , Java 7 und Java 8 heruntergeladen werden .Anwendungsbeispiel
Und Beispielausgabe,
quelle
NULL_IV_GENERATOR
vom Spring-Dienstprogramm verwendete ist nicht sicher. Wenn die Anwendung keine IV bereitstellt, lassen Sie den Anbieter diese auswählen und fragen Sie sie nach der Initialisierung ab.Nachdem ich die Vorschläge von erickson gelesen und aus ein paar anderen Beiträgen und diesem Beispiel hier herausgefunden habe, was ich konnte , habe ich versucht, Dougs Code mit den empfohlenen Änderungen zu aktualisieren. Fühlen Sie sich frei zu bearbeiten, um es besser zu machen.
Einige Hinweise: Hierbei wird ein 128-Bit-Verschlüsselungsschlüssel verwendet. Java führt anscheinend keine sofort einsatzbereite 256-Bit-Verschlüsselung durch. Für die Implementierung von 256 müssen einige zusätzliche Dateien im Java-Installationsverzeichnis installiert werden.
Ich bin auch keine Krypto-Person. Pass auf dich auf.
quelle
printStackTrace()
CipherInputStream
undCipherOutputStream
ist kein großes Problem. Das Mischen aller Ausnahmen unter der Tabelle ist ein Problem. Die Tatsache, dass das Salz plötzlich zu einem Feld geworden ist und dass die Infusion erforderlich ist, ist ein Problem. Die Tatsache, dass es nicht den Java-Codierungskonventionen entspricht, ist ein Problem. Und die Tatsache, dass dies nur bei Dateien funktioniert, wenn nicht danach gefragt wurde, ist ein Problem. Und dass der Rest des Codes im Grunde eine Kopie ist, hilft auch nicht. Aber vielleicht werde ich es optimieren, um es besser zu machen, wie vorgeschlagen ...Das Generieren eines eigenen Schlüssels aus einem Byte-Array ist einfach:
Das Erstellen eines 256-Bit-Schlüssels reicht jedoch nicht aus. Wenn der Schlüsselgenerator keine 256-Bit-Schlüssel für Sie generieren kann, unterstützt die
Cipher
Klasse wahrscheinlich auch kein AES-256-Bit. Sie sagen, Sie haben den Patch für die unbegrenzte Gerichtsbarkeit installiert, daher sollte die AES-256-Verschlüsselung unterstützt werden (aber auch 256-Bit-Schlüssel, sodass dies möglicherweise ein Konfigurationsproblem darstellt).Eine Problemumgehung wegen mangelnder AES-256-Unterstützung besteht darin, eine frei verfügbare Implementierung von AES-256 als benutzerdefinierten Anbieter zu verwenden. Dazu müssen Sie eine eigene
Provider
Unterklasse erstellen und mit verwendenCipher.getInstance(String, Provider)
. Dies kann jedoch ein komplizierter Prozess sein.quelle
Cipher
, nicht im Anbieter selbst. Sie können AES-256 in Java 8 und niedriger verwenden, benötigen jedoch eine proprietäre API. Oder eine Laufzeit, die natürlich keine Einschränkungen für die Schlüsselgröße darstellt.Was ich in der Vergangenheit getan habe, ist, den Schlüssel über etwas wie SHA256 zu hashen und dann die Bytes aus dem Hash in das Schlüsselbyte [] zu extrahieren.
Nachdem Sie Ihr Byte [] haben, können Sie einfach tun:
quelle
Cipher aes256 = Cipher.getInstance("AES/OFB/NoPadding"); MessageDigest keyDigest = MessageDigest.getInstance("SHA-256"); byte[] keyHash = keyDigest.digest(secret.getBytes("UTF-8")); SecretKeySpec key = new SecretKeySpec(keyHash, "AES"); aes256.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(initializationVector));
Ich mache auch das Gleiche wie in Ihrer Antwort vorgeschlagen, aber am Ende habe ich immer noch diese java.security.InvalidKeyException: Unzulässige Schlüsselgröße Ist das Herunterladen der JCE-Richtliniendatei obligatorisch?Zusätzlich zu den Änderungen von @ Wufoo verwendet die folgende Version InputStreams anstelle von Dateien, um die Arbeit mit einer Vielzahl von Dateien zu vereinfachen. Außerdem werden IV und Salt am Anfang der Datei gespeichert, sodass nur das Kennwort nachverfolgt werden muss. Da IV und Salz nicht geheim sein müssen, erleichtert dies das Leben ein wenig.
quelle
(Vielleicht hilfreich für andere mit einer ähnlichen Anforderung)
Ich hatte eine ähnliche Anforderung,
AES-256-CBC
um in Java zu verschlüsseln und zu entschlüsseln.Um die 256-Byte-Verschlüsselung / -Entschlüsselung zu erreichen (oder anzugeben),
Java Cryptography Extension (JCE)
sollte die Richtlinie auf festgelegt werden"Unlimited"
Es kann in der
java.security
Datei unter$JAVA_HOME/jre/lib/security
(für JDK) oder$JAVA_HOME/lib/security
(für JRE) eingestellt werden.crypto.policy=unlimited
Oder im Code als
In Java 9 und späteren Versionen ist dies standardmäßig aktiviert.
quelle
Erwägen Sie die Verwendung von Encryptor4j, dessen Autor ich bin.
Stellen Sie zunächst sicher, dass Sie Dateien mit Richtlinien für die Zuständigkeit für unbegrenzte Stärke installiert haben, bevor Sie fortfahren, damit Sie 256-Bit-AES-Schlüssel verwenden können.
Dann machen Sie folgendes:
Sie können jetzt den Verschlüsseler verwenden, um Ihre Nachricht zu verschlüsseln. Sie können auch eine Streaming-Verschlüsselung durchführen, wenn Sie möchten. Es generiert automatisch eine sichere IV und stellt diese vor.
Wenn es sich um eine Datei handelt, die Sie komprimieren möchten, sehen Sie sich diese Antwort an. Verschlüsseln einer großen Datei mit AES mit JAVA für einen noch einfacheren Ansatz.
quelle
Verwenden Sie diese Klasse zur Verschlüsselung. Es klappt.
Und das sind ivBytes und ein zufälliger Schlüssel;
quelle