Kryptering og dekryptering af filer i Java

Java Top

Jeg har lige annonceret det nye Lær foråret kursus med fokus på det grundlæggende i Spring 5 og Spring Boot 2:

>> KONTROLLER KURSEN

1. Oversigt

I denne vejledning ser vi på, hvordan du krypterer og dekrypterer en fil ved hjælp af eksisterende JDK API'er.

2. Skrivning af en test først

Vi starter med at skrive vores test, TDD-stil. Da vi skal arbejde med filer her, synes en integrationstest at være passende.

Da vi bare bruger eksisterende JDK-funktionalitet, er der ikke behov for eksterne afhængigheder.

Først, vi krypterer indholdet ved hjælp af en nyligt genereret hemmelig nøgle (vi bruger AES, Advanced Encryption Standard, som den symmetriske krypteringsalgoritme i dette eksempel).

Bemærk også, at vi definerer den komplette transformationsstreng i konstruktøren (AES / CBC / PKCS5Padding), som er en sammenkædning af brugt kryptering, blokcrypteringstilstand og polstring (algoritme / tilstand / polstring). JDK-implementeringer understøtter en række forskellige transformationer som standard, men vær opmærksom på, at ikke alle kombinationer stadig kan betragtes som kryptografisk sikre efter nutidens standarder.

Vi antager vores FileEncrypterDecrypter klasse skriver output til en fil, der hedder baz.enc. Bagefter, vi dekrypterer denne fil ved hjælp af den samme hemmelige nøgle og kontroller, at det dekrypterede indhold svarer til det oprindelige indhold:

@Test offentlig ugyldig nårEncryptingIntoFile_andDecryptingFileAgain_thenOriginalStringIsReturned () {String originalContent = "foobar"; SecretKey secretKey = KeyGenerator.getInstance ("AES"). CreateKey (); FileEncrypterDecrypter fileEncrypterDecrypter = ny FileEncrypterDecrypter (secretKey, "AES / CBC / PKCS5Padding"); fileEncrypterDecrypter.encrypt (originalContent, "baz.enc"); String decryptedContent = fileEncrypterDecrypter.decrypt ("baz.enc"); assertThat (decryptedContent, is (originalContent)); ny fil ("baz.enc"). slet (); // Ryd op }

3. Kryptering

Vi initialiserer chifferet i konstruktøren af ​​vores FileEncrypterDecrypter klasse ved hjælp af den angivne transformation Snor.

Dette giver os mulighed for at mislykkes tidligt, hvis der blev angivet en forkert transformation:

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

Det kan vi så Brug den instantierede chiffer og den medfølgende hemmelige nøgle til at udføre krypteringen:

ugyldig kryptering (strengindhold, strengfilnavn) {cipher.init (Cipher.ENCRYPT_MODE, secretKey); byte [] iv = cipher.getIV (); prøv (FileOutputStream fileOut = ny FileOutputStream (filnavn); CipherOutputStream cipherOut = ny CipherOutputStream (fileOut, cipher)) {fileOut.write (iv); cipherOut.write (content.getBytes ()); }}

Java tillader os at udnytte det praktiske CipherOutputStream klasse til at skrive det krypterede indhold til et andet OutputStream.

Bemærk, at vi skriver IV (initialiseringsvektor) til begyndelsen af ​​outputfilen. I dette eksempel genereres IV automatisk ved initialisering af Kryptering.

Brug af en IV er obligatorisk, når du bruger CBC-tilstand for at randomisere den krypterede output. IV betragtes dog ikke som en hemmelighed, så det er okay at skrive det i starten af ​​filen.

4. Dekryptering

For at dekryptere skal vi også læse IV først. Derefter kan vi initialisere vores chiffer og dekryptere indholdet.

Igen kan vi bruge en speciel Java-klasse, CipherInputStream, der gennemsigtigt tager sig af den faktiske dekryptering:

String decrypt (String fileName) {String content; prøv (FileInputStream fileIn = ny FileInputStream (fileName)) {byte [] fileIv = ny byte [16]; fileIn.read (fileIv); cipher.init (Cipher.DECRYPT_MODE, secretKey, nye IvParameterSpec (fileIv)); prøv (CipherInputStream cipherIn = ny CipherInputStream (fileIn, cipher); InputStreamReader inputReader = ny InputStreamReader (cipherIn); BufferedReader læser = ny BufferedReader (inputReader)) {StringBuilder sb = ny StringBuilder (); Streng linje; mens ((line = reader.readLine ())! = null) {sb.append (line); } indhold = sb.toString (); }} returner indhold }

5. Konklusion

Vi har set, at vi kan udføre grundlæggende kryptering og dekryptering ved hjælp af standard JDK-klasser, såsom Kryptering, CipherOutputStream og CipherInputStream.

Som sædvanlig er den komplette kode til denne artikel tilgængelig i vores GitHub-arkiv.

Derudover kan du finde en liste over de koder, der er tilgængelige i JDK her.

Endelig skal du bemærke, at kodeeksemplerne her ikke er beregnet som produktionskvalitetskode, og at det specifikke ved dit system skal overvejes grundigt når du bruger dem.

Java bund

Jeg har lige annonceret det nye Lær foråret kursus med fokus på det grundlæggende i Spring 5 og Spring Boot 2:

>> KONTROLLER KURSEN