Kryptering og dekryptering av filer i Java

Java Top

Jeg kunngjorde nettopp det nye Lær våren kurs, med fokus på det grunnleggende i vår 5 og vårstøvel 2:

>> KONTROLLER KURSET

1. Oversikt

I denne veiledningen tar vi en titt på hvordan du krypterer og dekrypterer en fil ved hjelp av eksisterende JDK APIer.

2. Skrive en test først

Vi begynner med å skrive vår test, TDD-stil. Siden vi skal jobbe med filer her, ser det ut til at en integrasjonstest er passende.

Siden vi bare bruker eksisterende JDK-funksjonalitet, er ingen eksterne avhengigheter nødvendig.

Først, vi krypterer innholdet ved hjelp av en nylig generert hemmelig nøkkel (vi bruker AES, Advanced Encryption Standard, som den symmetriske krypteringsalgoritmen i dette eksemplet).

Vær også oppmerksom på at vi definerer den komplette transformasjonsstrengen i konstruktøren (AES / CBC / PKCS5Padding), som er en sammenkobling av brukt kryptering, blokk krypteringsmodus og polstring (algoritme / modus / polstring). JDK-implementeringer støtter en rekke forskjellige transformasjoner som standard, men vær oppmerksom på at ikke alle kombinasjoner fremdeles kan betraktes som kryptografisk sikre etter dagens standarder.

Vi antar våre FileEncrypterDecrypter klasse vil skrive utdataene til en fil som heter baz.enc. Etterpå, vi dekrypterer denne filen ved hjelp av den samme hemmelige nøkkelen og sjekk at dekryptert innhold er lik det opprinnelige innholdet:

@Test offentlig ugyldig nårEncryptingIntoFile_andDecryptingFileAgain_thenOriginalStringIsReturned () {String originalContent = "foobar"; SecretKey secretKey = KeyGenerator.getInstance ("AES"). GenerateKey (); 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"). delete (); // rydde opp }

3. Kryptering

Vi initialiserer krypteringen i konstruktøren av vår FileEncrypterDecrypter klasse ved hjelp av den spesifiserte transformasjonen String.

Dette lar oss mislykkes tidlig i tilfelle en feil transformasjon ble spesifisert:

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

Vi kan da bruk den instantierte krypteringen og den medfølgende hemmelige nøkkelen til å utføre krypteringen:

ugyldig kryptering (String content, String fileName) {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 tillater oss å utnytte det praktiske CipherOutputStream klasse for å skrive det krypterte innholdet til et annet OutputStream.

Vær oppmerksom på at vi skriver IV (initialiseringsvektor) til begynnelsen av utdatafilen. I dette eksemplet genereres IV automatisk når den initialiseres Kryptering.

Bruk av IV er obligatorisk når du bruker CBC-modus, for å randomisere den krypterte utgangen. IV er imidlertid ikke ansett som en hemmelighet, så det er greit å skrive den i begynnelsen av filen.

4. Dekryptering

For å dekryptere må vi også lese IV først. Etterpå kan vi initialisere krypteringen og dekryptere innholdet.

Igjen kan vi bruke en spesiell Java-klasse, CipherInputStream, som transparent tar seg av den faktiske dekrypteringen:

String dekryptere (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 reader = ny BufferedReader (inputReader)) {StringBuilder sb = ny StringBuilder (); Streng linje; mens ((line = reader.readLine ())! = null) {sb.append (line); } innhold = sb.toString (); }} returner innhold; }

5. Konklusjon

Vi har sett at vi kan utføre grunnleggende kryptering og dekryptering ved hjelp av standard JDK-klasser, for eksempel Kryptering, CipherOutputStream og CipherInputStream.

Som vanlig er den fullstendige koden for denne artikkelen tilgjengelig i GitHub-arkivet.

I tillegg kan du finne en liste over kodene som er tilgjengelige i JDK her.

Til slutt, vær oppmerksom på at kodeeksemplene her ikke er ment som produksjonsgradskode, og at spesifikasjonene til systemet ditt må vurderes grundig når du bruker dem.

Java bunn

Jeg kunngjorde nettopp det nye Lær våren kurs, med fokus på det grunnleggende i vår 5 og vårstøvel 2:

>> KONTROLLER KURSET