[Java] AES Verschlüsselung

Dieses Thema im Forum "Programmierung & Entwicklung" wurde erstellt von YOOUI, 9. Februar 2013 .

  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
     
  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....
     
  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
     
  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.
     
  5. 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.
     
  6. Video Script

    Videos zum Themenbereich

    * gefundene Videos auf YouTube, anhand der Überschrift.