15.2.3 | Symmetrische Verschlüsselung |
Die für die symmetrische Verschlüsselung benötigten Klassen sind hauptsächlich im Paket javax.crypto definiert. In Analogie zum Hashing gibt es auch hier eine Klasse, die den Algorithmus repräsentiert (Cipher), sowie Stream-Klassen, die die Ver- und Entschlüsselung größerer Datenmengen vereinfachen (DigestInputStream und DigestOutputStream).
Nachfolgend wird ein Beispiel für die Stream-Verschlüsselung im Rahmen eines kleinen Programms zur Dateiverschlüsselung gezeigt. Dieses Programm leitet den symmetrischen Schlüssel aus dem Hash über einem Passwort ab. Hierzu wird die aus dem Hash gewonnene Bytefolge mit der Klasse SecretKeySpec in einen TripleDES-Schlüssel überführt. Dieser Schlüssel wird durch ein Exemplar der Klasse Key dargestellt, mit dem seinerseits ein Cipher-Objekt initialisiert werden kann.protected final Cipher initCipher(boolean encryptMode) throws IOException, GeneralSecurityException { // Passwort-Hash berechnen und Schlüssel aufbereiten byte[] rawKey = initSymmetricKey(encryptMode); // Initialisierung des TripleDES-Schlüssels Key key; key = new SecretKeySpec( new DESedeKeySpec(rawKey).getKey(), ENC_ALG); // Initialisierung des Cipher-Objekts Cipher cipher; cipher = Cipher.getInstance(ENC_ALG); if (encryptMode) cipher.init(Cipher.ENCRYPT_MODE, key); else cipher.init(Cipher.DECRYPT_MODE, key); return cipher; }Mit dem Cipher-Objekt kann jetzt die eigentliche Verschlüsselung mit den genannten Stream-Klassen erfolgen. Zur Integritätssicherung berechnet die Verschlüsselungsroutine des Beispielprogramms zunächst einen Hash über die Quelldatei, der dann am Anfang der verschlüsselten Datei gespeichert wird. Beim Entschlüsseln kann dieser Hash dann mit dem verglichen werden, den der Empfänger über den Ursprungsdaten ermittelt. Stimmen beide überein, wurde die Datei nicht manipuliert.public void encryptFile(String srcFileName, String dstFileName) throws IOException, GeneralSecurityException { MessageDigest md; InputStream srcStream; CipherOutputStream cipherStream; // MessageDigest-Exemplar erzeugen md = MessageDigest.getInstance(HASH_ALG); // Einen Stream mit diesem Exemplar erzeugen srcStream = new DigestInputStream(new FileInputStream(srcFileName), md); // Datei einmal einlesen, um den Hash zu berechnen byte[] buffer = new byte[BUFSIZE]; while(srcStream.read(buffer) != -1); srcStream.close(); // Hash abrufen byte[] hash = md.digest(); // Cipher-Objekt initialisieren Cipher cipher = initCipher(true); srcStream = new FileInputStream(srcFileName); // Cipher-Stream über einem FileOutputStream erzeugen cipherStream = new CipherOutputStream(new FileOutputStream(dstFileName), cipher); // Hash verschlüsselt in die Datei schreiben cipherStream.write(hash); int len; // Daten aus der Quelldatei // in den Cipher-Stream schreiben while ((len = srcStream.read(buffer)) != -1) cipherStream.write(buffer, 0, len); srcStream.close(); cipherStream.close(); }Analog arbeitet die Methode zum Entschlüsseln.Material zum Beispiel
- Quelltexte: