Java: AES Verschlüsselung mit Beispiel

Java VerschlüsselungDie letzten Wochen ging es heiß her: Nicht nur die Temperaturen in Deutschland waren extrem, sondern auch die Enthüllung von PRISM und co. Dabei entscheidet jeder selbst, welche Dienste er nutzt und was er verschlüsseln will. Auf dem Markt gibt es viele verschiedene Technologien, wie zum Beispiel:

  1. PGP-Verschlüsselung und Signatur für E-Mails oder Dateien
  2. AES oder IDEA für Texte

Heute zeige ich kurz und knapp, wie man eine AES-Verschlüsselung mit Java realisiert.

 

AES Key aus einem String generieren

Das A und O einer symmetrischen Verschlüsselung ist der Schlüssel. Dabei gibt es viele verschiedene Wege einen Schlüssel zu generieren. Eine Möglichkeit ist das Generieren eines zufälligen Keys (Habe ich hier beschrieben und den Schlüssel in eine Datei geschrieben) oder man generiert sich einen Key aus einem String/Text.

		// Das Passwort bzw der Schluesseltext
		String keyStr = "geheim";
		// byte-Array erzeugen
		byte[] key = (keyStr).getBytes("UTF-8");
		// aus dem Array einen Hash-Wert erzeugen mit MD5 oder SHA
		MessageDigest sha = MessageDigest.getInstance("SHA-256");
		key = sha.digest(key);
		// nur die ersten 128 bit nutzen
		key = Arrays.copyOf(key, 16); 
		// der fertige Schluessel
		SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");

 

Text mit AES verschlüsseln

Die meiste Arbeit ist bereits getan – mit dem Schlüssel kann man nun beliebige Texte verschlüsseln:

		// der zu verschl. Text
		String text = "Das ist der Text";

		// Verschluesseln
		Cipher cipher = Cipher.getInstance("AES");
		cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
		byte[] encrypted = cipher.doFinal(text.getBytes());

		// bytes zu Base64-String konvertieren (dient der Lesbarkeit)
		BASE64Encoder myEncoder = new BASE64Encoder();
		String geheim = myEncoder.encode(encrypted);

		// Ergebnis
		System.out.println(geheim);

 

Text mit AES entschlüsseln

Das Ganze kann man natürlich auch umdrehen:

		// der verschl. Text
		String geheim = "jcZyVG7CAfD+FQ9gAkhbfwzRD+tpKxeq8GRh+ub/uuc=";

		// BASE64 String zu Byte-Array konvertieren
		BASE64Decoder myDecoder2 = new BASE64Decoder();
		byte[] crypted2 = myDecoder2.decodeBuffer(geheim);

		// Entschluesseln
		Cipher cipher2 = Cipher.getInstance("AES");
		cipher2.init(Cipher.DECRYPT_MODE, secretKeySpec);
		byte[] cipherData2 = cipher2.doFinal(crypted2);
		String erg = new String(cipherData2);

		// Klartext
		System.out.println(erg);

 

Das gesamte Beispiel

package axxg;

import java.security.MessageDigest;
import java.util.Arrays;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class AxxGBlog {

	/**
	 * @param args
	 * @throws Exception 
	 */
	public static void main(String[] args) throws Exception {

		
		// Das Passwort bzw der Schluesseltext
		String keyStr = "geheim";
		// byte-Array erzeugen
		byte[] key = (keyStr).getBytes("UTF-8");
		// aus dem Array einen Hash-Wert erzeugen mit MD5 oder SHA
		MessageDigest sha = MessageDigest.getInstance("SHA-256");
		key = sha.digest(key);
		// nur die ersten 128 bit nutzen
		key = Arrays.copyOf(key, 16); 
		// der fertige Schluessel
		SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
		

		// der zu verschl. Text
		String text = "Das ist der Text";

		// Verschluesseln
		Cipher cipher = Cipher.getInstance("AES");
		cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
		byte[] encrypted = cipher.doFinal(text.getBytes());

		// bytes zu Base64-String konvertieren (dient der Lesbarkeit)
		BASE64Encoder myEncoder = new BASE64Encoder();
		String geheim = myEncoder.encode(encrypted);

		// Ergebnis
		System.out.println(geheim);
		
		// BASE64 String zu Byte-Array konvertieren
		BASE64Decoder myDecoder2 = new BASE64Decoder();
		byte[] crypted2 = myDecoder2.decodeBuffer(geheim);

		// Entschluesseln
		Cipher cipher2 = Cipher.getInstance("AES");
		cipher2.init(Cipher.DECRYPT_MODE, secretKeySpec);
		byte[] cipherData2 = cipher2.doFinal(crypted2);
		String erg = new String(cipherData2);

		// Klartext
		System.out.println(erg);

	}

}

 

Die Quellen

 

Copyright © 2013 AxxG – Alexander Gräsel



10 Antworten : “Java: AES Verschlüsselung mit Beispiel”

  1. tester sagt:

    Die meiste Arbeite <-Rechtschreibfehler 😉

  2. Raphael sagt:

    Vielen Dank für deinen Beitrag. Um das Beispiel aber in der Realtität verwenden zu können möchte ich eine Klasse mit zwei Funktionen encrypt und decrypt schreiben. Ich frage mich nun ob das SecretKeySpec Objekt bei beiden das Gleiche sein muss, was ja aber in der Praxis nicht unbedingt machbar ist, da vielleicht die Entschlüsselung in einem viel späteren Zeitpunkt auftritt und das SecretKeySpec Objekt nicht verfügbar ist. Kannst du mir weiterhelfen? Ich frage dich das, weil ich es eben selber schon getestet habe und da bekam ich nicht bei der Entschlüsselung nicht mehr den Ursprungstext zurück..

  3. Eric sagt:

    Toller Artikel, vielen Danke dafür :).

    @Raphael.

    Das SecretKeySpec Objekt wird ja mithilfe des Strings keyStr, welcher vorher in das key array umgewandelt wird, erzeugt.

    Du kannst das SecretKeySpec Objekt also ruhig neu erzeugen, musst dabei nur den selben keyStr benutzen. 🙂

    Viele Grüße

  4. Bastian sagt:

    Hey, echt coole Anleitung! Es hat mir sehr weitergeholfen!

    Allerdings gab es bei mir Probleme mit den BASE64Encoder und -Decoder Klassen. Er hat sie nicht gefunden (kann auch sein, dass ich einen Fehler gemacht habe, ich bin in Java ziemlich neu). Für alle die aber auch darüber stolpern sollten, ich konnte aus der java.util.Base64 Klasse mittels Base64.Encoder myEncoder = Base64.getEncoder() ein Objekt erzeugen.

    Eine kleine Frage hätte ich noch, vielleicht weiß da jemand eine gute Lösung. Zur Zeit wird der Schlüssel für die Verschlüsselung noch im Quelltext gespeichert. Das ist an sich ja schon ziemlich unsicher, da man den Bytecode jederzeit wieder zu Klartext zurückkonvertierten kann. Gibt es einen Weg den Schlüssel ohne riesigen Aufwand zu sichern?

    • Hey Bastian,
      schön, dass dir mein Beitrag gefällt:)

      @Base64
      Das Problem habe ich schon hier beschrieben;-)
      http://blog.axxg.de/java-kodierung-base64/

      @Speicherung des Keys
      Das ist immer das größte Problem. Die Lösung: Es gibt keine Pauschallösung:-/
      + Auf Android hat man die Möglichkeit den Key in einem sicheren Speicherbereich des Prozessors oder im security Element abzulegen.
      + Auf Windows und co kann man den AES Schlüssel per RSA/SSL auf den Client zur Laufzeit übertragen und mit Hardware-Spec’s verschlüsseln.
      + Man kann den Schlüssel aus einer Zeitvorgabe oder einen Key generieren
      + etc…….
      Such dir was aus;-)

  5. Fabian sagt:

    ACHTUNG! Hier wird die AES-Chiffre im ECB-Modus gezeigt! Das ist höchst fahrlässig und unsicher!
    Bitte lesen: https://de.wikipedia.org/wiki/Electronic_Code_Book_Mode

    Weiter oben wird dann einfach auch ein Schlüssel per MD5 erzeugt. Man mag meinen, dass man da ja auch kein Hash zb. für Benutzeranmeldungen in ne Datenbank bringen will und das ausreiche. Falsch! Ein starker Hash zb. per PBKDF2 und ausreichend gesalzen ist auch hier essenziell! Stichwort: Brute-Forcing mit Wörterbuch! Mit MD5 geht das rasend schnell!

    Ich hoffe, dass das jeder liest, der diese Seite besucht. Ich selbst bin auch kein Kryptograph, aber das hier ist offensichtlich.

    • Hey Fabian,
      erstmal danke für deinen Kommentar.

      zu 1. ECB-Modus
      Der Beitrag richtet sich an Anfänger, die noch nichts mit AES gemacht haben. Daher gilt: je einfach desto besser. Wer einen anderen Modus nutzen will, kann gerne die Zeile 38 durch
      Cipher.getInstance(„AES/CBC/NoPadding“);
      ersetzen;-)

      2. der Schlüssel
      Siehe Oben;-) Ich zeige eine einfache Möglichkeit – mehr nicht, aber ich habe mal das Beispiel gegen SHA ersetzt….

Kommentar verfassen