Nun kommen wir zur ersten „richtigen“ Verschlüsselung, bei der wir den Advanced Encryption Standard oder kurz AES nutzen werden. Auch wenn die Ausgabe recht schmucklos daherkommt, ist bereits diese einfache Version eine vollständige und mit „Hausmitteln“ nicht zu knackende Verschlüsselung… wenn ein paar Punkte berücksichtigt werden (später dazu mehr).
Erst einmal der Steckbrief:
Verschlüsselungssteckbrief | |
Name des Verfahrens | AES/ECB/NOPADDING |
Langname | ECB Electronic Code Book |
Art der Chiffre | Blockchiffre |
Blocklänge (Byte) | 16 |
Schlüssellänge (Byte/Bit) | 16/128, 24/192, 32/256 |
Padding genutzt | Nein |
Sicherheit | nur bei kleinen Datenmengen |
Besonderes | Nein |
Wie arbeitet diese Routine ? Es werden immer Blöcke von exakt 16 Zeichen verschlüsselt und ausgegeben, wobei es zum vorherigen und nachfolgenden Block keine Verbindung gibt. Die Entschlüsselung erfolgt ebenso in Blöcken von 16 Byte.
Das Programm kann auf 2 Eingabezeilen reduziert werden – in Zeile 38 wird der zu verschlüsselnde Text definiert und die Zeile 47 enthält den (geheimen) Schlüssel für die Ver- und Entschlüsselung. Die Länge des Schlüssels definiert zugleich die Verschlüsselungsstärke der AES-Routine und kann 3 Längen haben: 16 Byte (entspricht 128 Bit), 24 Byte (192 Bit) oder32 Byte (256 Bit). An dieser Stelle gebe ich noch einmal den Hinweis, das Ihr Euer Java System auf unlimitierte Verschlüsselung testet, sonst kann es später zu Fehlermeldungen kommen.
Spielt also aus Spaß mal mit einem längeren Schlüsseln in dem Ihr z.B. in Zeile 47 schreibt – das Programm arbeitet wie verlangt.
final byte[] keyByte = „12345678901234561234567890123456“.getBytes(„UTF-8“);
Nun probiert einmal einen Schlüssel der ein Byte länger oder kürzer ist: nach dem Start hagelt es eine Fehlermeldung das der Schlüssel nicht passend ist.
Weiterhin könnt Ihr ausprobieren, wie das Programm auf einen plaintext reagiert, der doppelt so lang wie der Demonstrationstext ist (also 32 Zeichen lang ist). .. und was passiert, wenn der plaintext 15 oder 17 Zeichen lang ist ?
Falls es Dich interessiert, warum ich die rot geschrieben Warnung nachfolgend dort hinschreibe, solltest Du die zweite Seite aufrufen.
Bitte die nachfolgende Routine nicht für den Echteinsatz nutzen, da sie aus kryptographischer Sicht sehr angreifbar ist ! Eine optische Erläuterung für meine Einschätzung findet Ihr in der Rubrik Unsicherheit unter G01 ECB Pinguin.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
package net.bplaced.javacrypto.symmetricencryption; /* * Herkunft/Origin: http://javacrypto.bplaced.net/ * Programmierer/Programmer: Michael Fehr * Copyright/Copyright: frei verwendbares Programm (Public Domain) * Copyright: This is free and unencumbered software released into the public domain. * Lizenttext/Licence: <http://unlicense.org> * getestet mit/tested with: Java Runtime Environment 8 Update 191 x64 * Datum/Date (dd.mm.jjjj): 01.11.2018 * Funktion: verschlüsselt einen string im aes ecb modus ohne padding * Function: encrypts a string using aes ecb modus without a padding * * Sicherheitshinweis/Security notice * Die Programmroutinen dienen nur der Darstellung und haben keinen Anspruch auf eine * korrekte Funktion, insbesondere mit Blick auf die Sicherheit ! * Prüfen Sie die Sicherheit bevor das Programm in der echten Welt eingesetzt wird. * The program routines just show the function but please be aware of the security part - * check yourself before using in the real world ! */ import java.io.UnsupportedEncodingException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.spec.SecretKeySpec; import javax.xml.bind.DatatypeConverter; public class B03_AesEcbNopaddingString { public static void main(String[] args) throws UnsupportedEncodingException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { System.out.println("B03 AES im Betriebsmodus ECB NoPadding mit einem String"); // es werden ein paar variablen benötigt: // String plaintextString = "HalloWelt0123456"; // exakt 16 zeichen String plaintextString = "HalloWelt0123456"; // exakt 16 zeichen String decryptedtextString = ""; // enthält später den entschlüsselten text // diese konstanten und variablen benötigen wir zur ver- und entschlüsselung // der genutzte algorithmus // der schlüssel ist exakt 32 zeichen lang und bestimmt die stärke der // verschlüsselung // hier ist der schlüssel 32 byte = 256 bit lang // mögliche schlüssellängen sind 16 byte (128 bit), 24 byte (192 bit) und 32 // byte (256 bit) // final byte[] keyByte = "1234567890123456".getBytes("UTF-8"); // 16 byte final byte[] keyByte = "12345678901234567890123456789012".getBytes("UTF-8"); // 32 byte byte[] plaintextByte = null; // der verschluesselte (encrypted) text kommt in diese variable in form eines // byte arrays byte[] ciphertextByte = null; // die länge steht noch nicht fest, da sie von der größe des plaintextes abhängt // der entschlüsselte (decrypted) text kommt in dieses byte array, welches // später in einen string umkodiert wird byte[] decryptedtextByte = null; // die länge steht noch nicht fest, da sie von der größe des plaintextes // abhängt // ab hier arbeiten wir nun im verschlüsselungsmodus // umwandlung des klartextes in ein byte array plaintextByte = plaintextString.getBytes("UTF-8"); // der schlüssel wird in die richtige form gebracht SecretKeySpec keySpec = new SecretKeySpec(keyByte, "AES"); // die verschlüsselungsroutine wird mit dem gewünschten parameter erstellt Cipher aesCipherEnc = Cipher.getInstance("AES/ECB/NOPADDING"); // nun wird die routine mit dem schlüssel initialisiert aesCipherEnc.init(Cipher.ENCRYPT_MODE, keySpec); // hier erfolgt nun die verschlüsselung des plaintextes ciphertextByte = aesCipherEnc.doFinal(plaintextByte); // ab hier arbeiten wir nun im entschlüsselungsmodus // die verschlüsselungsroutine wird mit dem gewünschten parameter erstellt Cipher aesCipherDec = Cipher.getInstance("AES/ECB/NOPADDING"); // zum einsatz kommt derselbe schlüssel, daher symmetrische verschlüsselung // achtung: hier wird der DECRYPT_MODE = entschlüsselung genutzt aesCipherDec.init(Cipher.DECRYPT_MODE, keySpec); // nun wird der ciphertext wieder entschlüsselt decryptedtextByte = aesCipherDec.doFinal(ciphertextByte); // zurück-kodierung des byte array in text decryptedtextString = new String(decryptedtextByte, "UTF-8"); // ausgabe der variablen System.out.println(""); System.out.println("keyByte (hex) :" + DatatypeConverter.printHexBinary(keyByte)); System.out.println("plaintextString :" + plaintextString); System.out.println("plaintextByte (hex) :" + DatatypeConverter.printHexBinary(plaintextByte)); System.out.println("= = = Verschlüsselung = = ="); System.out.println("ciphertextByte (hex) :" + DatatypeConverter.printHexBinary(ciphertextByte)); System.out.println("= = = Entschlüsselung = = ="); System.out.println("decryptedtextByte (hex):" + DatatypeConverter.printHexBinary(decryptedtextByte)); System.out.println("decryptedtextString :" + decryptedtextString); } } |
Die Ausgabe des Programms sieht so aus:
1 2 3 4 5 6 7 8 |
keyByte (hex) :3132333435363738393031323334353637383930313233343536373839303132 plaintextString :HalloWelt0123456 plaintextByte (hex) :48616C6C6F57656C7430313233343536 = = = Verschlüsselung = = = ciphertextByte (hex) :1A35BD2BE60E8598FDCA34C004320D05 = = = Entschlüsselung = = = decryptedtextByte (hex):48616C6C6F57656C7430313233343536 decryptedtextString :HalloWelt0123456 |
Die Lizenz zum obigen Beispiel findet Ihr auf der eigenen Lizenz-Seite.
Letzte Aktualisierung: 18.11.2018