Ver- und Entschlüsseln von Dateien in Java

Java Top

Ich habe gerade den neuen Learn Spring- Kurs angekündigt , der sich auf die Grundlagen von Spring 5 und Spring Boot 2 konzentriert:

>> Überprüfen Sie den Kurs

1. Übersicht

In diesem Tutorial erfahren Sie, wie Sie eine Datei mit vorhandenen JDK-APIs verschlüsseln und entschlüsseln.

2. Schreiben Sie zuerst einen Test

Wir beginnen mit dem Schreiben unseres Tests im TDD-Stil. Da wir hier mit Dateien arbeiten werden, scheint ein Integrationstest angebracht zu sein.

Da wir nur vorhandene JDK-Funktionen verwenden, sind keine externen Abhängigkeiten erforderlich.

Zuerst verschlüsseln wir den Inhalt mit einem neu generierten geheimen Schlüssel (in diesem Beispiel verwenden wir AES, Advanced Encryption Standard, als symmetrischen Verschlüsselungsalgorithmus).

Beachten Sie auch, dass wir die vollständige Transformationszeichenfolge im Konstruktor ( AES / CBC / PKCS5Padding ) definieren, bei der es sich um eine Verkettung der verwendeten Verschlüsselung, des Blockverschlüsselungsmodus und des Auffüllens ( Algorithmus / Modus / Auffüllen ) handelt. JDK-Implementierungen unterstützen standardmäßig eine Reihe verschiedener Transformationen. Beachten Sie jedoch, dass nach heutigen Standards nicht jede Kombination als kryptografisch sicher angesehen werden kann.

Wir gehen davon aus, dass unsere FileEncrypterDecrypter- Klasse die Ausgabe in eine Datei namens baz.enc schreibt . Anschließend entschlüsseln wir diese Datei mit demselben geheimen Schlüssel und prüfen, ob der entschlüsselte Inhalt dem ursprünglichen Inhalt entspricht:

@Test public void whenEncryptingIntoFile_andDecryptingFileAgain_thenOriginalStringIsReturned() { String originalContent = "foobar"; SecretKey secretKey = KeyGenerator.getInstance("AES").generateKey(); FileEncrypterDecrypter fileEncrypterDecrypter = new FileEncrypterDecrypter(secretKey, "AES/CBC/PKCS5Padding"); fileEncrypterDecrypter.encrypt(originalContent, "baz.enc"); String decryptedContent = fileEncrypterDecrypter.decrypt("baz.enc"); assertThat(decryptedContent, is(originalContent)); new File("baz.enc").delete(); // cleanup }

3. Verschlüsselung

Wir initialisieren die Verschlüsselung im Konstruktor unserer FileEncrypterDecrypter- Klasse unter Verwendung der angegebenen Transformationszeichenfolge .

Dies ermöglicht es uns, frühzeitig zu scheitern, falls eine falsche Transformation angegeben wurde:

FileEncrypterDecrypter(SecretKey secretKey, String transformation) { this.secretKey = secretKey; this.cipher = Cipher.getInstance(transformation); }

Wir können dann die instanziierte Verschlüsselung und den bereitgestellten geheimen Schlüssel verwenden, um die Verschlüsselung durchzuführen:

void encrypt(String content, String fileName) { cipher.init(Cipher.ENCRYPT_MODE, secretKey); byte[] iv = cipher.getIV(); try (FileOutputStream fileOut = new FileOutputStream(fileName); CipherOutputStream cipherOut = new CipherOutputStream(fileOut, cipher)) { fileOut.write(iv); cipherOut.write(content.getBytes()); } }

Mit Java können wir die praktische CipherOutputStream- Klasse nutzen, um den verschlüsselten Inhalt in einen anderen OutputStream zu schreiben .

Bitte beachten Sie, dass wir den IV (Initialization Vector) an den Anfang der Ausgabedatei schreiben. In diesem Beispiel wird die IV beim Initialisieren der Verschlüsselung automatisch generiert .

Die Verwendung einer IV ist im CBC-Modus obligatorisch, um die verschlüsselte Ausgabe zufällig zu sortieren. Die IV wird jedoch nicht als Geheimnis angesehen, daher ist es in Ordnung, sie am Anfang der Datei zu schreiben.

4. Entschlüsselung

Zum Entschlüsseln müssen wir ebenfalls zuerst die IV lesen. Anschließend können wir unsere Verschlüsselung initialisieren und den Inhalt entschlüsseln.

Auch hier können wir eine spezielle Java-Klasse verwenden, CipherInputStream , die sich transparent um die eigentliche Entschlüsselung kümmert :

String decrypt(String fileName) { String content; try (FileInputStream fileIn = new FileInputStream(fileName)) { byte[] fileIv = new byte[16]; fileIn.read(fileIv); cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(fileIv)); try ( CipherInputStream cipherIn = new CipherInputStream(fileIn, cipher); InputStreamReader inputReader = new InputStreamReader(cipherIn); BufferedReader reader = new BufferedReader(inputReader) ) { StringBuilder sb = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { sb.append(line); } content = sb.toString(); } } return content; }

5. Schlussfolgerung

Wir haben gesehen, dass wir eine grundlegende Ver- und Entschlüsselung mit Standard-JDK-Klassen wie Cipher , CipherOutputStream und CipherInputStream durchführen können .

Der vollständige Code für diesen Artikel ist wie üblich in unserem GitHub-Repository verfügbar.

Außerdem finden Sie hier eine Liste der im JDK verfügbaren Chiffren.

Beachten Sie schließlich, dass die Codebeispiele hier nicht als Code für die Produktion gedacht sind und die Besonderheiten Ihres Systems bei der Verwendung sorgfältig berücksichtigt werden müssen.

Java unten

Ich habe gerade den neuen Learn Spring- Kurs angekündigt , der sich auf die Grundlagen von Spring 5 und Spring Boot 2 konzentriert:

>> Überprüfen Sie den Kurs