#1 9. Februar 2013 Zuletzt bearbeitet: 9. Februar 2013 AES Verschlüsselung Hi RR-Community, ich habe eine AES Verschlüsselungsklasse in Java geschrieben... Und da ich ganz neu auf diesem Gebiet bin, würde ich nur gerne von euch wissen wie sicher sie ist, und wie man sie gegeben Falles verbessern könnte. Klasse: Spoiler Code: // Klassen importieren import java.io.DataOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.security.GeneralSecurityException; import java.security.Key; import java.security.NoSuchAlgorithmException; import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; public class file_crypter { //Key private Key key; //Konstruktor //#key -> Ent-/Verschlüsselungspasswort public file_crypter(String password) throws NoSuchAlgorithmException, UnsupportedEncodingException { key = buildKey(password); } //Verschlüsselungsfunktion //#inputFile -> zu Verschlüsselnde Datei //#outputFile -> Datei in der die Verschlüsslete Version gespeichert werden soll public void encrypt(String inputFile, String outputFile) throws IOException, GeneralSecurityException { //AES als Verschlüsselungsalgorythmus auswählen Cipher cipher = Cipher.getInstance("AES"); //Verschlüsselungsmodus auswählen cipher.init(Cipher.ENCRYPT_MODE, key); //inputFile einlesen InputStream in = new FileInputStream(inputFile); //outputFile einlesen/erstellen DataOutputStream out = new DataOutputStream(new FileOutputStream(outputFile)); //Datei verschlüsseln mit Hilfe der Funktion 'crypt' crypt(in, out, cipher); } //Entschlüsselungsfunktion //#inputFile -> Die Verschlüsselte Datei //#outputFile -> Datei in der die Entschlüsselte Version gespeichert werden soll public void decrypt(String inputFile, String outputFile) throws IOException, GeneralSecurityException { //AES als Verschlüsselungsalgorythmus auswählen Cipher cipher = Cipher.getInstance("AES"); //Entschlüsselungsmodus auswählen cipher.init(Cipher.DECRYPT_MODE, key); //inputFile einlesen InputStream in = new FileInputStream(inputFile); //outputFile einlesen/erstellen DataOutputStream out = new DataOutputStream(new FileOutputStream(outputFile)); //Datei verschlüsseln mit Hilfe der Funktion 'crypt' crypt(in, out, cipher); } //Cyrpt Funktion - Eigentliche Verschlüsselungsfunktion //#in -> Input-Dateistream //#ou -> Output-Dateistream //#cipher -> JavaEigene Verschlüsselungfunktion private void crypt(InputStream in, OutputStream out, Cipher cipher) throws IOException, GeneralSecurityException { int blockSize = cipher.getBlockSize(); int outputSize = cipher.getOutputSize(blockSize); byte[] input = new byte[blockSize]; byte[] output = new byte[outputSize]; int inLength = 0; boolean finished = false; while (!finished) { inLength = in.read(input); if (inLength == blockSize) { int outLength = cipher.update(input, 0, blockSize, output); out.write(output, 0, outLength); } else { finished = true; } } if (inLength > 0) output = cipher.doFinal(input, 0, inLength); else output = cipher.doFinal(); out.write(output); } //Passwort erstellungs Funktion //#password -> Userpasswort private static Key buildKey(String password) throws NoSuchAlgorithmException, UnsupportedEncodingException { //Salt-Array zum auffüllen der Passworts, falls es zu kurz ist final char[] salt_array = "lsdijfOJ%/iizuIUZq0asduhw3KHGO(/V86tbIUHE&$EDZ09iuoztcz54GVIU".toCharArray(); int i = 0; //Solange passwort zu kurz ist, um Zeichen aus salt_array erweitern while(password.getBytes().length < 16) { password = password + salt_array[i]; i++; } //Passwort in das richtige Format bringen SecretKeySpec spec = new SecretKeySpec(password.getBytes("UTF-8"), "AES"); return spec; } } Mit freundlichen Grüßen, yooui p.S. Das es eine symmetrische Verschlüsselung ist, war beabsichtigt + Multi-Zitat Zitieren
#2 9. Februar 2013 Zuletzt bearbeitet: 9. Februar 2013 AW: AES Verschlüsselung In wie fern verbessern? Schneller machen, oder sicherer? Denkst du nicht , wenn es eine Möglichkeit gäbe gravierende Verbesserungen zu machen, dass dies schon geschehen wäre?^^ Du kannst aber Anpassungen tätigen, allerdings rate ich dir nur dazu, wenn du ein wirklich tiefgehendes Verständnis der Materie hast... Viele Änderungen verschlechtern dern Algo nur ungemein.... Du kannst aber prinzipiell alle Änderungen an den Rundenschlüsseln, sowie den Textregistern machen, die umkehrbar sind ;-) Jedoch bringt das natürlich nur was, wenn der entschlüsselnde diese Implementierung auch hat. Ebenso kannst die die Schlüssellänge (sowie so halt..) erhöhen. /// BTW hast du keine AES Implementierung geschrieben, sondern nur eine Nutzung der AES Schnittstelle in Java. Wenn du tiefgehende Änderungen machen willst, schreib die Implementierung selber.... + Multi-Zitat Zitieren
#3 9. Februar 2013 AW: AES Verschlüsselung Hi Smoker, ich habe mich wohl etwas falsch ausgedrückt, ich will nicht die Verschlüsselung selber verbessern, sondern wollte nur wissen ob ich alles richtig programmiert habe....und nicht irgendwelche Anfängerfehler gemacht habe, die den Code unsicherer machen. LG yooui p.S. Die Tage erhöhe ich die Schlüssellänge auf 32 Byte, dann scheint mir die Verschlüsselung an sich sicher genug + Multi-Zitat Zitieren
#4 9. Februar 2013 AW: AES Verschlüsselung Nicht unbedingt unsicher, aber unleserlich. Sorry, das gehört eben dazu: Code: public class file_crypter { Klassenamen immer in UpperCamelCase. Bei Methoden hast du die öffnende Klammer '{' in einer neuen Zeile, also mach das hier auch (nachfolgend gehe ich daher von K&R aus). Code: public file_crypter Nicht vergessen den Konstruktor dann auch anzupassen. Code: public void encrypt(...) ... { '{' in eine neue Zeile. Code: //AES als Verschlüsselungsalgorythmus auswählen Cipher cipher = Cipher.getInstance("AES"); //Verschlüsselungsmodus auswählen cipher.init(Cipher.ENCRYPT_MODE, key); InputStream in = new FileInputStream(inputFile); //outputFile einlesen/erstellen DataOutputStream out = new DataOutputStream(new FileOutputStream(outputFile)); //Datei verschlüsseln mit Hilfe der Funktion 'crypt' crypt(in, out, cipher); Das passiert wenn man Tabs und Leerzeichen vermischt. Mach es gleich einheitlich, dann hast du solche Probleme gar nicht und man erkennt Copy&Paste nicht Code: public void decrypt(...) ... { Siehe encrypt(...) (auch wieder Tabfehler) Code: private void crypt(...) ... { Tab vor '{' weg. Code: while(password.getBytes().length < 16) { '{' kommt nicht in eine neue Zeile. + Multi-Zitat Zitieren
#5 9. Februar 2013 AW: AES Verschlüsselung Die Implementierung ist ziemlich unsicher, wegen dem ECB Mode. Electronic Code Book Mode – Wikipedia CBC sollte es schon sein. + Multi-Zitat Zitieren
#6 20. Februar 2013 Zuletzt bearbeitet: 20. Februar 2013 So besser ? Ist das jetzt so besser/sicherer? Spoiler Code: // Klassen importieren import java.io.DataOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.security.GeneralSecurityException; import java.security.Key; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; public class fileCrypter{ //Key private Key key; //Anzahl der Verschlüsselungsdurchläufe int RundenAnzahl = 4; //Konstruktor //#key -> Ent-/Verschlüsselungspasswort public fileCrypter(String password) throws NoSuchAlgorithmException, UnsupportedEncodingException { key = buildKey(password); } //Verschlüsselungsfunktion //#inputFile -> zu Verschlüsselnde Datei //#outputFile -> Datei in der die Verschlüsslete Version gespeichert werden soll public void encrypt(String inputFile, String outputFile) throws IOException, GeneralSecurityException { //AES als Verschlüsselungsalgorythmus auswählen Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); //IvParameter byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; IvParameterSpec ivspec = new IvParameterSpec(iv); //Verschlüsselungsmodus auswählen cipher.init(Cipher.ENCRYPT_MODE, key, ivspec); //inputFile einlesen InputStream in = new FileInputStream(inputFile); //outputFile einlesen/erstellen DataOutputStream out = new DataOutputStream(new FileOutputStream(outputFile)); //Datei verschlüsseln mit Hilfe der Funktion 'crypt' crypt(in, out, cipher); } //Entschlüsselungsfunktion //#inputFile -> Die Verschlüsselte Datei //#outputFile -> Datei in der die Entschlüsselte Version gespeichert werden soll public void decrypt(String inputFile, String outputFile) throws IOException, GeneralSecurityException { //AES als Verschlüsselungsalgorythmus auswählen Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; IvParameterSpec ivspec = new IvParameterSpec(iv); //Entschlüsselungsmodus auswählen cipher.init(Cipher.DECRYPT_MODE, key, ivspec); //inputFile einlesen InputStream in = new FileInputStream(inputFile); //outputFile einlesen/erstellen DataOutputStream out = new DataOutputStream(new FileOutputStream(outputFile)); //Datei verschlüsseln mit Hilfe der Funktion 'crypt' crypt(in, out, cipher); } //Cyrpt Funktion - Eigentliche Verschlüsselungsfunktion //#in -> Input-Dateistream //#ou -> Output-Dateistream //#cipher -> JavaEigene Verschlüsselungfunktion private void crypt(InputStream in, OutputStream out, Cipher cipher) throws IOException, GeneralSecurityException { int blockSize = cipher.getBlockSize(); int outputSize = cipher.getOutputSize(blockSize); byte[] input = new byte[blockSize]; byte[] output = new byte[outputSize]; int inLength = 0; boolean finished = false; while (!finished) { inLength = in.read(input); if (inLength == blockSize) { int outLength = cipher.update(input, 0, blockSize, output); out.write(output, 0, outLength); } else { finished = true; } } if (inLength > 0) output = cipher.doFinal(input, 0, inLength); else output = cipher.doFinal(); out.write(output); } //Passwort erstellungs Funktion //#password -> Userpasswort private Key buildKey(String password) throws NoSuchAlgorithmException, UnsupportedEncodingException { //Passwort in das richtige Format bringen SecretKeySpec spec = new SecretKeySpec(sha256Hash(passwordIncreaser(password)), "AES"); return spec; } private byte[] sha256Hash(String passwort) throws NoSuchAlgorithmException, UnsupportedEncodingException { MessageDigest md = MessageDigest.getInstance("SHA-256"); md.update(passwort.getBytes("UTF-8")); // Change this to "UTF-16" if needed return md.digest(); } private String passwordIncreaser(String password) { //Salt-Array zum auffüllen der Passworts, falls es zu kurz ist final char[] salt_array = "scdfdsc.oisrjnoiu40p8ouümß9oimäxposdkcfp0wn5utnaocixjdüßc0".toCharArray(); int i = 0; //Solange passwort zu kurz ist, um Zeichen aus salt_array erweitern while(password.getBytes().length < salt_array.length) { password = salt_array[((salt_array.length - 1) - i)] + password + salt_array[i]; i++; } return password; } } Ich frage mich noch, warum es alles 'zerschießt' (das Program geht einwandfrei, aber der Output ist Sinnlos/Leer) wenn ich als Input + Output Stream die gleiche Datei habe? LG yooui p.S. Habe leider noch nicht die Zeit und Motivation gehabt die Einrückungen zu berichtigen. + Multi-Zitat Zitieren
#7 23. Februar 2013 AW: AES Verschlüsselung IV sollte nicht ein null array sein, sondern auch random. Da fällt mir auf, dass dein Passwort-Generator viel zu unsicher ist. Key stretching - Wikipedia, the free encyclopedia PBKDF2 am besten benutzen... mindestens 1000 Iterationen. + Multi-Zitat Zitieren