Freitag, 28. Oktober 2011

Secret-Key Verschlüsselung/Entschlüsselung

Zuerst einmal muss das Passwort mit einem Salt versehen werden und aus diesem Pärchen mittels der SecretKeyFactoryein SecretKey erzeugt werden:
char[] password = "Test".toCharArray();
byte salt[] = new byte[] {0, 1 };

SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec spec = new PBEKeySpec(password, salt, 1024, 256);
SecretKey tmp = factory.generateSecret(spec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
Im Beispiel ist das Salt fest - dieses sollte ansonsten natürlich zufällig erzeugt werden. Wichtig ist, dass bei einer zufälligen Erzeugung das Salt auch an die entschlüsselnde Partei übergeben werden muss. Der dritte Parameter der  PBEKeySpec gibt die Anzahl der Iterationen an, der vierte die Größe des Schlüssels. Die Größe des Schlüssels beeinflusst auch die Stärke des AES.

Für die Verschlüsselung wird nun die Cipher erzeugt und initialisiert.
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret);
Der Init-Vector muss sich gemerkt (und an die entschüsselnde Partei übergeben) werden! Dies kann z.B. geschehen, indem die Daten an den Anfang des Streams geschrieben werden.
AlgorithmParameters p = cipher.getParameters();
byte[] iv = p.getParameterSpec(IvParameterSpec.class).getIV();
Nun kann der Input (z.B. mit Hilfe eines CipherOutputStream) verschlüsselt werden:
CipherOutputStream cos = new CipherOutputStream(out, cipher);
cos.write("Test".getBytes("UTF-8"));
cos.close();
Zum Entschlüsseln muss die Cipher nun mit dem IV initialisiert werden:
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
Danach kann (z.B. mit Hilfe eines CipherInputStream) die Entschlüsselung durchgeführt werden:
CipherInputStream cis = new CipherInputStream(in, cipher);
byte[] buffer = new byte[1024];
int readBytes = cis.read(buffer);