Ersten bytes fehlerhaft nach Java AES/CBC-Entschlüsselung
Was ist falsch an dem folgenden Beispiel?
Das problem ist, dass der erste Teil der entschlüsselten Zeichenfolge ist Unsinn. Jedoch der rest ist in Ordnung, ich bekomme...
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();
}
}
- VERWENDEN SIE KEINE ANTWORT AUF DIESE FRAGE IM ERNST ! Alle Beispiel-in dieser Frage sind anfällig für padding oracle und sind insgesamt sehr schlechte Kryptographie-Nutzung. Sie präsentieren Ihr ernsthafte Kryptographie Sicherheitslücke in Ihrem Projekt, indem Sie das Codefragment unten.
- Hi @HoLyVieR, könnten Sie ein Beispiel geben für eine bessere Kryptographie-Algorithmus? Es ist wahr, was Sie sagen, aber ich habe festgestellt, das Artikel meri-Zeug.blogspot.com.ar/2012/04/..., die erklärt, wie Sie zu überwinden Polsterung oracle und erläutert, einen anderen Schwachstellen
- Sie sollte nicht entwickeln Sie Ihre eigenen Verschlüsselungs-Bibliothek in den ersten Platz. Durch die Verwendung der code, den Sie entwickeln Ihre eigenen Kryptographie-Bibliothek. Tun Sie dies nicht und verwenden Sie ein high-level-API, die Ihre Rahmen liefert oder verwenden Sie eine Bibliothek, die bieten high-level-API.
- In Bezug auf die folgenden Zitate: "Man sollte nicht entwickeln Sie Ihre eigenen Verschlüsselungs-Bibliothek" und "verwenden Sie ein high-level-API, die Ihr framework bietet." Niemand hier ist die Entwicklung eigener Kryptographie-Bibliothek. Wir sind einfach mit der bereits vorhandenen, high-level-API, das java-framework bietet. Sie sir sind Wild ungenau.
- Sie sind definitiv nicht "high level cryptography" - API. Als eine gute Faustregel, wenn Sie eingeben oder kopieren/einfügen AES, Sie sind nicht mit einem high-level-Kryptographie-API. Richtig Montage AES mit dem richtigen Algorithmus, um zu verhindern, dass die kryptographischen Angriff ist schwer, und Sie sollten es vermeiden, es zu tun, wenn Sie haben keine Erfahrung in der Kryptographie. Du bist nur shooting selbst in den Fuß, ohne es zu merken.
- Fair genug Punkt über unsichere Beispiele, fühlen Sie sich frei, um einen Kommentar zu hinterlassen. Soweit diese Frage geht, ich war immer gestartet und brauchte nur etwas Hilfe mit einer konkreten Frage. Gute Entwickler werden die notwendigen Untersuchungen, wie sicher etwas ist, schlechten Entwickler nicht.
- Nur weil Sie beide einverstanden sind, bedeutet nicht, dass Sie beide richtig sind. Gute Entwickler kennen den Unterschied zwischen der Verpackung eines high-level-API und umschreiben einer low-level-API. Gut Leser wird bemerken, dass der OP fragte nach einem "einfachen java-AES-verschlüsseln/entschlüsseln-Beispiel" und das ist genau das, was er bekam. Ich weiß auch nicht einverstanden mit den anderen Antworten, das ist, warum ich geschrieben eine Antwort auf meine eigenen. Vielleicht haben Sie Jungs sollten versuchen, die gleiche und erleuchte uns alle mit Ihrem know-how.
- Ich habe angefangen, eine Diskussion auf Meta statt. Fühlen Sie sich frei, beitragen. Beachten Sie, dass ich nicht darüber einig, was eigentlich gefragt. Ich legte die tatsächliche Frage unter den mitgelieferten Beispiel-code in die Frage (die ich nicht Bearbeiten Sie die Frage selbst).
- danke für den link. Ich habe bearbeitet Sie meine post.
- Ich habe "Sie sollte nicht entwickeln Sie Ihre eigenen Verschlüsselungs-Bibliothek in den ersten Platz". Ernst Folgen Sie diesem Rat. Ihr framework (und auch viele library) geben Sie Weg, um Daten zu verschlüsseln, ohne zu wählen, Verschlüsselung und cipher-Modus. Verwenden Sie Sie ! Die low-level-API von Java haben viele Vorbehalte, die zu lange zu erklären, die in einem der Kommentare.
- Das ist wirklich die absurdeste Sache, die ich je gelesen habe auf SO! Wer bist du den Leuten sagen, was Sie können und können sich nicht entwickeln?
- Ich sehe immer noch keine Beispiele @HoLyVieR. Mal sehen, einige, oder Verweise auf Bibliotheken? Nicht konstruktiv bei allen.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Viele Menschen, einschließlich mir Gesicht viele Probleme, die in dieser Arbeit aufgrund fehlender Informationen, wie, vergessen zu konvertieren, Base64 -, Initialisierungs-Vektoren, Zeichensatz, etc. Also habe ich darüber nachgedacht, eine voll funktionsfähige code.
Hoffe, das wird hilfreich sein für Euch alle:
Zum kompilieren benötigt man zusätzliche Apache-Commons-Codec-Glas, die hier verfügbar ist:
http://commons.apache.org/proper/commons-codec/download_codec.cgi
System.out.println("encrypted string:" + DatatypeConverter.printBase64Binary(encrypted));
byte[] original = cipher.doFinal(DatatypeConverter.parseBase64Binary(encrypted));
SecureRandom
android.util.Base64
. Der code, den ich verwendet istreturn Base64.encodeToString(encrypted, Base64.DEFAULT);
undbyte[] original = cipher.doFinal(Base64.decode(encrypted, Base64.DEFAULT));
.return Base64.getEncoder().encodeToString(encrypted);
und in der decrypt-Methode:byte[] original = cipher.doFinal(Base64.getDecoder().decode(encrypted));
Arrays.fill(iv, (byte) 0x00)
mitnew SecureRandom().nextBytes(iv)
?Hier eine Lösung ohne
Apache-Commons-Codec
'sBase64
:Beispiel:
Drucke:
encrypt(String)
und nichtencrypt(byte[] )
?. Verschlüsselung (Entschlüsselung auch) ist eine byte-basierte Verfahren (AES ist sowieso). Die Verschlüsselung dauert bytes als Eingabe-und Ausgänge Byte, so funktioniert die Entschlüsselung (case in point : dieCipher
- Objekt gibt). Nun, einen bestimmten Anwendungsfall kann sein, wenn die verschlüsselten bytes aus einem String oder gesendet werden als Zeichenkette (base64 MIME-Anhang zu einer E-Mail...), aber das ist eine Frage, die die Kodierung der bytes, für die gibt es Hunderte von Lösungen, die völlig ohne Bezug zu AES/Verschlüsselung.Strings
da ist im Grunde, was ich mit 95% der Zeit und Sie am Ende der Konvertierung sowieso.Sieht für mich wie Sie haben es nicht ordnungsgemäß mit dem Initialisierungsvektor (IV).
Es ist schon eine lange Zeit, seit ich zuletzt gelesen über die AES -, IVs-und block-chaining, aber Ihre Linie
scheint nicht OK zu sein. Im Falle von AES, kann man sich den Initialisierungsvektor als "Anfangszustand" eines cipher-Instanz, und dieser Zustand ist ein bisschen von Informationen, die Sie können nicht aus Ihrer Schlüssel, aber von der eigentlichen Berechnung des zu verschlüsseln, chiffrieren. (Man könnte argumentieren, dass, wenn der IV gewonnen werden können, aus dem Schlüssel, dann wäre es nicht von nutzen, da der Schlüssel bereits an den Chiffre-Instanz während der init-phase).
Daher sollte man die IV als byte[] aus dem cipher-Instanz am Ende Ihrer Verschlüsselung
und sollten Sie initialisieren Ihre
Cipher
imDECRYPT_MODE
mit diesem byte[] :Dann, Ihr die Entschlüsselung sollte OK sein.
Hoffe, das hilft.
Die IV, die Ihre Verwendung für die Entschlüsselung falsch ist. Ersetzen Sie diesen code
Mit diesem code
Und das sollte Ihr problem lösen.
Unten enthält ein Beispiel für eine einfache AES-Klasse in Java. Ich weiß nicht empfehlen die Verwendung dieser Klasse in der Produktion-Umgebungen, wie es kann nicht Konto für alle spezifischen Anforderungen Ihrer Anwendung.
Beachten Sie, dass AES nichts zu tun hat mit dem codieren, das ist, warum ich entschied mich, es zu handhaben sind separat und ohne die Notwendigkeit von Bibliotheken Dritter.
"/NoPadding"
. CTR ist ein Modus, schaltet AES in einem stream-cipher und stream cipher arbeitet auf Byte anstelle von Blöcken.In dieser Antwort, die ich wählen, um den Ansatz der "Einfache Java-AES-verschlüsseln/entschlüsseln-Beispiel" main theme und nicht das spezifische debugging Frage, weil ich denke, dass dies ein Gewinn für die meisten Leser.
Dies ist eine einfache Zusammenfassung meiner blog post über die AES-Verschlüsselung in Java so empfehle ich das Lesen durch, bevor Sie Sie implementieren nichts. Ich werde jedoch noch ein einfaches Beispiel verwenden und einige Hinweise geben, was zu beachten.
In diesem Beispiel werde ich wählen, zu verwenden authentifizierte Verschlüsselung mit Galois/Counter-Modus oder GCM - Modus. Der Grund dafür ist, dass in den meisten Fällen Sie Integrität und Authentizität in Kombination mit der Vertraulichkeit (Lesen Sie mehr in der blog).
AES-GCM-Verschlüsselung/Entschlüsselung Tutorial
Hier sind die Schritte, die erforderlich sind, um zu verschlüsseln/entschlüsseln mit AES-GCM mit der Java Cryptography Architecture (JCA). Nicht mischen mit anderen Beispielen, da subtile Unterschiede möglicherweise Ihren code völlig unsicher.
1. Key
Als es hängt von deinem use-case, gehe ich davon aus einfachsten Fall: einen zufälligen geheimen Schlüssel.
Wichtig:
SecureRandom
2. Erstellen der Initialisierungsvektor
Einer die Initialisierung vector (IV) verwendet wird, so dass der gleiche geheime Schlüssel erstellen verschiedene Chiffre Texte.
Wichtig:
SecureRandom
3. Verschlüsseln mit IV und Key
Wichtig:
CipherInputStream
beim verschlüsseln von großen Blöcken von Datencipher.updateAAD(associatedData);
Mehr hier.3. Serialisieren, um Einzelne Nachricht
Nur Anhängen IV und ciphertext. Wie oben gesagt, der IV muss nicht geheim sein.
Optional Kodieren mit Base64 wenn Sie eine string-Darstellung. Entweder Android oder Java 8 ist built-in Umsetzung (verwenden Sie nicht die Apache-Commons-Codec - es ist eine schreckliche Umsetzung). Die Codierung wird verwendet, um den "convert" byte-arrays in string-Darstellung zu machen, es ASCII-safe z.B.:
4. Bereiten Entschlüsselung: Deserialisieren
Wenn Sie verschlüsselt die Nachricht zunächst entschlüsseln, um byte-array:
dann dekonstruieren die Nachricht
Wichtig:
5. Entschlüsseln
Initialisieren den Algorithmus (cipher) und die gleichen Parameter wie bei der Verschlüsselung:
Wichtig:
cipher.updateAAD(associatedData);
wenn Sie es während der Verschlüsselung.Beachten Sie, dass die meisten der jüngsten Android-SDK (21+) und Java (7+) - Implementierung AES-GCM. Ältere Versionen kann es fehlt. Ich noch wählen Sie diesen Modus aus, da es einfacher zu implementieren ist zudem effizienter im Vergleich zu ähnlichen Modus der Encrypt-dann-Mac (z.B. AES-CBC + HMAC). Finden Sie in diesem Artikel auf, wie zu implementieren AES-CBC mit HMAC.
this is true for CBC mode but not for GCM
meinst du das ganze Teil oder nur die, die es eigentlich nicht brauchen, unvorhersehbar zu sein?but I don't think that SO should be the place for this.
Sie sind wahrscheinlich Recht, aber es scheint, dass die meisten nur mit dem stick SO. Vielleicht sind die meisten der Benutzer wird nicht in der notwendigen Zeit, um vollständig zu verstehen, das Thema, aber vielleicht ein paar eingekerbt in die richtige Richtung - wie denken Sie, Anfänger guides veröffentlicht werden soll? Die Tatsache, dass z.B. in Java/JCE Architektur ist wirklich schwer zu verstehen, besonders für jemanden, der nicht aus der Kryptographie Studien - und es gibt kaum einen guten?Online-Editor Ausführbare version:-
Dies ist eine Verbesserung gegenüber der akzeptierten Antwort.
Änderungen:
(1) Mit zufälligen IV und voranzustellen, um den verschlüsselten text
(2) Mit SHA-256 zu erzeugen, einen Schlüssel aus einer passphrase
(3) Keine Abhängigkeit von Apache Commons
Oft ist es eine gute Idee, um verlassen sich auf standard-Bibliothek zur Verfügung gestellt Lösung:
Diese Drucke "Text zu Kodieren".
Lösung basiert auf Java Cryptography Architecture Reference Guide und https://stackoverflow.com/a/20591539/146745 Antwort.
Andere Lösung, die mit java.util.Base64 mit Spring Boot
Encryptor Klasse
EncryptorController Klasse
Anwendung.Eigenschaften
Beispiel
http://localhost:8082/cipher/encrypt/jmendoza
2h41HH8Shzc4BRU3hVDOXA==
http://localhost:8082/cipher/decrypt/2h41HH8Shzc4BRU3hVDOXA==
jmendoza
Github: https://github.com/JonathanM2ndoza/Spring-Boot-Crypto
Schließlich encryptation in java ist so einfach zu verwenden mit Java Simplified Encryption (Jasypt) , in einer anderen Weise, die Sie verwenden können, cypher, oben ist ein code-Beispiel zum verschlüsseln und entschlüsseln :