Fájlok titkosítása és visszafejtése Java-ban

Java Top

Most jelentettem be az újat Tanulj tavaszt tanfolyam, amelynek középpontjában az 5. tavasz és a tavaszi bakancs 2 alapjai állnak:

>> ELLENŐRIZZE A FOLYAMATOT

1. Áttekintés

Ebben az oktatóanyagban megvizsgáljuk, hogyan lehet titkosítani és visszafejteni a fájlokat a meglévő JDK API-k segítségével.

2. Először írjon tesztet

Kezdjük azzal, hogy megírjuk tesztünket, a TDD stílust. Mivel itt fájlokkal fogunk dolgozni, úgy tűnik, hogy egy integrációs teszt megfelelő.

Mivel csak a meglévő JDK funkciókat használjuk, nincs szükség külső függőségekre.

Első, titkosítjuk a tartalmat egy újonnan létrehozott titkos kulcs segítségével (ebben a példában szimmetrikus titkosítási algoritmusként az AES-t, az Advanced Encryption Standard szabványt használjuk).

Vegye figyelembe azt is, hogy a teljes transzformációs karakterláncot definiáljuk a konstruktorban (AES / CBC / PKCS5Padding), amely a használt titkosítás, a blokk titkosítási mód és a kitöltés összefűzése (algoritmus / mód / párnázás). A JDK implementációk alapértelmezés szerint számos különböző átalakítást támogatnak, de kérjük, vegye figyelembe, hogy a mai szabványok szerint még mindig nem tekinthető minden kombináció kriptográfiailag biztonságosnak.

Feltételezzük a mi FileEncrypterDecrypter osztály írja a kimenetet egy nevű fájlba baz.enc. Utána ezt a fájlt ugyanazon titkos kulcs segítségével visszafejtjük és ellenőrizze, hogy a visszafejtett tartalom megegyezik-e az eredeti tartalommal:

@Test public void whenEncryptingIntoFile_andDecryptingFileAgain_thenOriginalStringIsReturned () {String originalContent = "foobar"; SecretKey secretKey = KeyGenerator.getInstance ("AES"). GeneratorKey (); FileEncrypterDecrypter fileEncrypterDecrypter = új FileEncrypterDecrypter (secretKey, "AES / CBC / PKCS5Padding"); fileEncrypterDecrypter.encrypt (originalContent, "baz.enc"); String decryptedContent = fileEncrypterDecrypter.decrypt ("baz.enc"); assertThat (decryptedContent, is (originalContent)); új File ("baz.enc"). delete (); // takarítás}

3. Titkosítás

A titkosítást inicializáljuk a konstruktorunkban FileEncrypterDecrypter osztály a megadott transzformáció segítségével Húr.

Ez lehetővé teszi számunkra a korai kudarcot abban az esetben, ha helytelen átalakítást határoztak meg:

FileEncrypterDecrypter (SecretKey secretKey, String transzformáció) {this.secretKey = secretKey; this.cipher = Cipher.getInstance (transzformáció); }

Akkor megtehetjük használja a példányosított titkosítást és a mellékelt titkos kulcsot a titkosítás végrehajtásához:

void encrypt (karakterlánc tartalom, karakterlánc fájlnév) {cipher.init (Cipher.ENCRYPT_MODE, secretKey); bájt [] iv = rejtjel.getIV (); próbáld meg (FileOutputStream fileOut = új FileOutputStream (fájlnév); CipherOutputStream cipherOut = új CipherOutputStream (fileOut, rejtjel)) {fileOut.write (iv); cipherOut.write (content.getBytes ()); }}

A Java lehetővé teszi számunkra kihasználni a kényelmes CipherOutputStream osztály a titkosított tartalom másikba írására OutputStream.

Felhívjuk figyelmét, hogy az IV-t (Initialization Vector) a kimeneti fájl elejére írjuk. Ebben a példában a IV automatikusan generálódik a Rejtjel.

Az IV használata kötelező a CBC mód használatakor a titkosított kimenet véletlenszerűsítése érdekében. A IV azonban nem tekinthető titoknak, ezért rendben van, ha a fájl elejére írjuk.

4. Dekódolás

A visszafejtéshez először is el kell olvasnunk a IV. Utána inicializálhatjuk a rejtjelünket és visszafejthetjük a tartalmat.

Ismét használhatunk egy speciális Java osztályt, CipherInputStream, amely átláthatóan gondoskodik a tényleges visszafejtésről:

Karakterlánc visszafejtése (String fileName) {Karaktersorozat tartalma; próbáld meg (FileInputStream fileIn = új FileInputStream (fájlNév)) {byte [] fileIv = new byte [16]; fileIn.read (fileIv); cipher.init (Cipher.DECRYPT_MODE, secretKey, új IvParameterSpec (fileIv)); try (CipherInputStream cipherIn = new CipherInputStream (fileIn, cipher); InputStreamReader inputReader = new InputStreamReader (cipherIn); BufferedReader reader = new BufferedReader (inputReader)) {StringBuilder sb = új StringBuilder (); Vonósor; while ((line = olvasó.readLine ())! = null) {sb.append (sor); } tartalom = sb.toString (); }} return content; }

5. Következtetés

Láttuk, hogy az alapvető titkosítást és a visszafejtést szabványos JDK osztályok, például Rejtjel, CipherOutputStream és CipherInputStream.

Szokás szerint a cikk teljes kódja elérhető a GitHub adattárunkban.

Ezen felül itt találja a JDK-ban elérhető Cipherek listáját.

Végül vegye figyelembe, hogy az itt található kódpéldák nem termelési szintű kódként értendők, és a rendszer sajátosságait alaposan figyelembe kell venni azok használatakor.

Java alsó

Most jelentettem be az újat Tanulj tavaszt tanfolyam, amelynek középpontjában az 5. tavasz és a tavaszi bakancs 2 alapjai állnak:

>> ELLENŐRIZZE A FOLYAMATOT