Was ist los mit dem folgenden Beispiel?
Das Problem ist, dass der erste Teil der entschlüsselten Zeichenfolge Unsinn ist. Der Rest ist jedoch in Ordnung, ich verstehe ...
Result: `£eB6O�geS��i are you? Have a nice day.
@Test
public void testEncrypt() {
try {
String s = "Hello there. How are you? Have a nice day.";
// Generate key
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128);
SecretKey aesKey = kgen.generateKey();
// Encrypt cipher
Cipher encryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
encryptCipher.init(Cipher.ENCRYPT_MODE, aesKey);
// Encrypt
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
CipherOutputStream cipherOutputStream = new CipherOutputStream(outputStream, encryptCipher);
cipherOutputStream.write(s.getBytes());
cipherOutputStream.flush();
cipherOutputStream.close();
byte[] encryptedBytes = outputStream.toByteArray();
// Decrypt cipher
Cipher decryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
IvParameterSpec ivParameterSpec = new IvParameterSpec(aesKey.getEncoded());
decryptCipher.init(Cipher.DECRYPT_MODE, aesKey, ivParameterSpec);
// Decrypt
outputStream = new ByteArrayOutputStream();
ByteArrayInputStream inStream = new ByteArrayInputStream(encryptedBytes);
CipherInputStream cipherInputStream = new CipherInputStream(inStream, decryptCipher);
byte[] buf = new byte[1024];
int bytesRead;
while ((bytesRead = cipherInputStream.read(buf)) >= 0) {
outputStream.write(buf, 0, bytesRead);
}
System.out.println("Result: " + new String(outputStream.toByteArray()));
}
catch (Exception ex) {
ex.printStackTrace();
}
}
java
encryption
aes
TedTrippin
quelle
quelle
Antworten:
Viele Leute, einschließlich ich, haben viele Probleme damit, dass dies funktioniert, weil einige Informationen fehlen, wie das Vergessen, in Base64 zu konvertieren, Initialisierungsvektoren, Zeichensätze usw. Ich dachte daran, einen voll funktionsfähigen Code zu erstellen.
Ich hoffe, dies ist für Sie alle nützlich: Zum Kompilieren benötigen Sie eine zusätzliche Apache Commons Codec-JAR-Datei, die hier verfügbar ist: http://commons.apache.org/proper/commons-codec/download_codec.cgi
quelle
System.out.println("encrypted string:" + DatatypeConverter.printBase64Binary(encrypted));
byte[] original = cipher.doFinal(DatatypeConverter.parseBase64Binary(encrypted));
SecureRandom
Hier ist eine Lösung ohne
Apache Commons Codec
‚sBase64
:Anwendungsbeispiel:
Drucke:
quelle
encrypt(String)
und nichtencrypt(byte[] )
? Die Verschlüsselung (auch die Entschlüsselung) ist ein bytebasierter Prozess (AES ist es sowieso). Die Verschlüsselung verwendet Bytes als Eingabe und gibt Bytes aus, ebenso die Entschlüsselung (Beispiel: DasCipher
Objekt tut dies). Ein besonderer Anwendungsfall kann nun darin bestehen, verschlüsselte Bytes aus einem String zu haben oder als String gesendet zu werden (base64-MIME-Anhang für eine Mail ...). Dies ist jedoch ein Problem beim Codieren von Bytes, für das Hunderte von Bytes vorhanden sind Lösungen, die völlig unabhängig von AES / Verschlüsselung sind.Strings
da ich in 95% der Fälle damit arbeite und Sie trotzdem konvertieren.Sieht für mich so aus, als würden Sie mit Ihrem Initialisierungsvektor (IV) nicht richtig umgehen. Es ist lange her, dass ich das letzte Mal über AES, IVs und Blockverkettung gelesen habe, aber über Ihre Linie
scheint nicht in Ordnung zu sein. Im Fall von AES können Sie sich den Initialisierungsvektor als den "Anfangszustand" einer Verschlüsselungsinstanz vorstellen, und dieser Zustand ist eine Information, die Sie nicht von Ihrem Schlüssel erhalten können, sondern von der tatsächlichen Berechnung der Verschlüsselungsverschlüsselung. (Man könnte argumentieren, dass wenn die IV aus dem Schlüssel extrahiert werden könnte, dies keinen Nutzen hätte, da der Schlüssel der Verschlüsselungsinstanz bereits während ihrer Init-Phase übergeben wird.)
Daher sollten Sie die IV am Ende Ihrer Verschlüsselung als Byte [] von der Verschlüsselungsinstanz abrufen
und Sie sollten Ihr
Cipher
InDECRYPT_MODE
mit diesem Byte [] initialisieren :Dann sollte Ihre Entschlüsselung in Ordnung sein. Hoffe das hilft.
quelle
Die IV, die Sie zur Entschlüsselung verwenden, ist falsch. Ersetzen Sie diesen Code
Mit diesem Code
Und das sollte Ihr Problem lösen.
Unten finden Sie ein Beispiel für eine einfache AES-Klasse in Java. Ich empfehle nicht, diese Klasse in Produktionsumgebungen zu verwenden, da sie möglicherweise nicht alle spezifischen Anforderungen Ihrer Anwendung berücksichtigt.
Beachten Sie, dass AES nichts mit Codierung zu tun hat, weshalb ich mich dafür entschieden habe, es separat und ohne die Notwendigkeit von Bibliotheken von Drittanbietern zu behandeln.
quelle
"/NoPadding"
. CTR ist ein Modus, der AES in einer Stream-Verschlüsselung aktiviert, und eine Stream-Verschlüsselung verarbeitet Bytes anstelle von Blöcken.In dieser Antwort gehe ich auf das Hauptthema "Einfaches Java AES-Verschlüsselungs- / Entschlüsselungsbeispiel" und nicht auf die spezifische Debugging-Frage ein, da ich denke, dass dies den meisten Lesern zugute kommt.
Dies ist eine einfache Zusammenfassung meines Blogposts über AES-Verschlüsselung in Java. Ich empfehle daher, ihn vor der Implementierung durchzulesen. Ich werde jedoch weiterhin ein einfaches Beispiel zur Verfügung stellen und einige Hinweise geben, worauf zu achten ist.
In diesem Beispiel werde ich die authentifizierte Verschlüsselung im Galois / Counter-Modus oder im GCM- Modus verwenden. Der Grund dafür ist, dass Sie in den meisten Fällen Integrität und Authentizität in Kombination mit Vertraulichkeit wünschen (lesen Sie mehr im Blog ).
AES-GCM-Tutorial zur Verschlüsselung / Entschlüsselung
Hier sind die Schritte zum Ver- / Entschlüsseln mit AES-GCM mit der Java Cryptography Architecture (JCA) . Nicht mit anderen Beispielen mischen , da subtile Unterschiede Ihren Code völlig unsicher machen können.
1. Schlüssel erstellen
Da es von Ihrem Anwendungsfall abhängt, gehe ich vom einfachsten Fall aus: einem zufälligen geheimen Schlüssel.
Wichtig:
SecureRandom
2. Erstellen Sie den Initialisierungsvektor
Ein Initialisierungsvektor (IV) wird verwendet, so dass derselbe geheime Schlüssel unterschiedliche Chiffretexte erzeugt .
Wichtig:
SecureRandom
3. Mit IV und Schlüssel verschlüsseln
Wichtig:
CipherInputStream
Option, wenn Sie große Datenmengen verschlüsselncipher.updateAAD(associatedData);
More verwenden.3. Serialisieren Sie zu einer einzelnen Nachricht
Fügen Sie einfach IV und Chiffretext hinzu. Wie oben erwähnt, muss die IV nicht geheim sein.
Optional mit Base64 codieren, wenn Sie eine Zeichenfolgendarstellung benötigen. Verwenden Sie entweder die integrierte Implementierung von Android oder Java 8 (verwenden Sie nicht den Apache Commons Codec - es ist eine schreckliche Implementierung). Die Codierung wird verwendet, um Byte-Arrays in eine Zeichenfolgendarstellung zu "konvertieren", um sie ASCII-sicher zu machen, z.
4. Entschlüsselung vorbereiten: Deserialisieren
Wenn Sie die Nachricht codiert haben, dekodieren Sie sie zuerst in ein Byte-Array:
Wichtig:
5. Entschlüsseln
Initialisieren Sie die Verschlüsselung und stellen Sie die gleichen Parameter wie bei der Verschlüsselung ein:
Wichtig:
cipher.updateAAD(associatedData);
wenn Sie es während der Verschlüsselung hinzugefügt.Ein funktionierendes Code-Snippet finden Sie in dieser Übersicht.
Beachten Sie, dass die neuesten Android- (SDK 21+) und Java- (7+) Implementierungen AES-GCM haben sollten. Ältere Versionen können es fehlen. Ich wähle immer noch diesen Modus, da er einfacher zu implementieren ist und nicht nur effizienter als der ähnliche Modus von Encrypt-then-Mac (z. B. AES-CBC + HMAC ). In diesem Artikel erfahren Sie, wie Sie AES-CBC mit HMAC implementieren .
quelle
this is true for CBC mode but not for GCM
meinst du den ganzen teil oder nur muss er eigentlich nicht unvorhersehbar sein?Online Editor Ausführbare Version: -
quelle
Es ist oft die gute Idee, sich auf eine von der Standardbibliothek bereitgestellte Lösung zu verlassen:
Dies druckt "Zu codierender Text".
Die Lösung basiert auf dem Java Cryptography Architecture Reference Guide und der Antwort https://stackoverflow.com/a/20591539/146745 .
quelle
Dies ist eine Verbesserung gegenüber der akzeptierten Antwort.
Änderungen:
(1) Verwenden Sie zufällige IV und stellen Sie sie dem verschlüsselten Text voran
(2) Verwenden von SHA-256 zum Generieren eines Schlüssels aus einer Passphrase
(3) Keine Abhängigkeit von Apache Commons
quelle
Eine andere Lösung mit java.util.Base64 mit Spring Boot
Verschlüsselungsklasse
EncryptorController-Klasse
application.properties
Beispiel
http: // localhost: 8082 / cipher / encrypt / jmendoza
2h41HH8Shzc4BRU3hVDOXA ==
http: // localhost: 8082 / cipher / decrypt / 2h41HH8Shzc4BRU3hVDOXA ==
jmendoza
quelle
Optimierte Version der akzeptierten Antwort.
Keine Bibliotheken von Drittanbietern
schließt IV in die verschlüsselte Nachricht ein (kann öffentlich sein)
Das Passwort kann beliebig lang sein
Code:
Verwendung:
Beispielausgabe:
quelle
e.printStackTrace()
in so genannten optimierten Code erwarten .