Mengenkripsi dan Mendekripsi File di Java

Java Top

Saya baru saja mengumumkan kursus Learn Spring baru , yang berfokus pada dasar-dasar Spring 5 dan Spring Boot 2:

>> LIHAT KURSUSnya

1. Ikhtisar

Dalam tutorial ini, kita akan melihat cara mengenkripsi dan mendekripsi file menggunakan JDK API yang ada.

2. Menulis Tes Dulu

Kami akan mulai dengan menulis tes kami, gaya TDD. Karena kami akan bekerja dengan file di sini, tes integrasi tampaknya sesuai.

Karena kami baru saja menggunakan fungsionalitas JDK yang ada, tidak ada ketergantungan eksternal yang diperlukan.

Pertama, kami akan mengenkripsi konten menggunakan kunci rahasia yang baru dibuat (kami menggunakan AES, Standar Enkripsi Lanjutan, sebagai algoritme enkripsi simetris dalam contoh ini).

Perhatikan juga, bahwa kami mendefinisikan string transformasi lengkap dalam konstruktor ( AES / CBC / PKCS5Padding ), yang merupakan rangkaian dari enkripsi yang digunakan, mode block cipher, dan padding ( algoritme / mode / padding ). Implementasi JDK mendukung sejumlah transformasi berbeda secara default, namun harap diperhatikan, bahwa tidak setiap kombinasi masih dapat dianggap aman secara kriptografis menurut standar saat ini.

Kami akan menganggap kelas FileEncrypterDecrypter kami akan menulis output ke file bernama baz.enc . Setelah itu, kami mendekripsi file ini menggunakan kunci rahasia yang sama dan memeriksa apakah konten yang didekripsi sama dengan konten asli:

@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. Enkripsi

Kami akan menginisialisasi sandi di konstruktor kelas FileEncrypterDecrypter kami menggunakan String transformasi yang ditentukan .

Ini memungkinkan kami untuk gagal lebih awal jika ada transformasi yang salah ditentukan:

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

Kami kemudian dapat menggunakan cipher yang dipakai dan kunci rahasia yang disediakan untuk melakukan enkripsi:

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()); } }

Java memungkinkan kita memanfaatkan kelas CipherOutputStream yang nyaman untuk menulis konten terenkripsi ke OutputStream lain .

Harap dicatat bahwa kami sedang menulis IV (Inisialisasi Vektor) di awal file keluaran. Dalam contoh ini, IV secara otomatis dibuat saat menginisialisasi Cipher .

Menggunakan IV adalah wajib saat menggunakan mode CBC, untuk mengacak keluaran yang dienkripsi. IV tidak dianggap rahasia, jadi tidak apa-apa menulisnya di awal file.

4. Dekripsi

Untuk mendekripsi kita juga harus membaca IV terlebih dahulu. Setelah itu, kami dapat menginisialisasi sandi kami dan mendekripsi konten.

Sekali lagi kita dapat menggunakan kelas Java khusus, CipherInputStream , yang secara transparan menangani dekripsi sebenarnya :

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. Kesimpulan

Kami telah melihat kami dapat melakukan enkripsi dan dekripsi dasar menggunakan kelas JDK standar, seperti Cipher , CipherOutputStream , dan CipherInputStream .

Seperti biasa, kode lengkap untuk artikel ini tersedia di repositori GitHub kami.

Selain itu, Anda dapat menemukan daftar Cipher yang tersedia di JDK di sini.

Terakhir, perhatikan bahwa contoh kode di sini tidak dimaksudkan sebagai kode tingkat produksi dan spesifikasi sistem Anda perlu dipertimbangkan secara menyeluruh saat menggunakannya.

Jawa bawah

Saya baru saja mengumumkan kursus Learn Spring baru , yang berfokus pada dasar-dasar Spring 5 dan Spring Boot 2:

>> LIHAT KURSUSnya