Vejledning til krypteringsklassen

1. Oversigt

Kort sagt, kryptering er processen med at kode en meddelelse, således at kun autoriserede brugere kan forstå eller få adgang til den.

Meddelelsen kaldet simpel tekst, er krypteret ved hjælp af en krypteringsalgoritme - a kryptering - generere ciphertext der kun kan læses af autoriserede brugere via dekryptering.

I denne artikel beskriver vi detaljeret kernen Kryptering klasse, som giver kryptografisk kryptering og dekrypteringsfunktionalitet i Java.

2. Krypteringsklasse

Java Cryptography Extension (JCE) er del af Java Cryptography Architecture (JCA) der giver en applikation kryptografiske chifre til datakryptering og dekryptering samt hashing af private data.

Det Kryptering klasse - placeret i javax.crypto pakke - danner kernen i JCE-rammen og giver funktionaliteten til kryptering og dekryptering.

2.1. Cipher Instantiation

At instantiere en Kryptering objekt, vi kalde det statiske getInstance metode, der sender navnet på den anmodede transformation. Eventuelt kan navnet på en udbyder angives.

Lad os skrive et eksempel på en klasse, der illustrerer instantiering af en Kryptering:

offentlig klasse Encryptor {public byte [] encryptMessage (byte [] meddelelse, byte [] keyBytes) kaster InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException {Cipher cipher = Cipher.getInstance ("AES / ECB / PKCS5Padding"); // ...}}

Transformationen AES / ECB / PKCS5Padding fortæller getInstance metode til at instantiere Kryptering objekt som en AES-chiffer med ECB-driftsform og PKCS5-polstringsplan.

Vi kan også instantiere Kryptering objekt ved kun at specificere algoritmen i transformationen:

Cipher cipher = Cipher.getInstance ("AES");

I dette tilfælde bruger Java udbydersspecifikke standardværdier til tilstanden og polstringsplanen.

Noter det getInstance vil kaste en NoSuchAlgorithmException hvis transformation er nul, tom eller i et ugyldigt format, eller hvis udbyderen ikke understøtter det.

Det vil kaste en NoSuchPaddingException hvis transformationen indeholder en ikke-understøttet polstringsplan.

2.2. Trådsikkerhed

Det Kryptering klasse er en stateful en uden nogen form for intern synkronisering. Faktisk er metoder som i det() eller opdater () vil ændre den interne tilstand for et bestemt Kryptering eksempel.

Derfor er den Kryptering klasse er ikke trådsikker. Så vi skal oprette en Kryptering forekomst pr. behov for kryptering / dekryptering.

2.3. Nøgler

Det Nøgle interface repræsenterer nøgler til kryptografiske operationer. Nøgler er uigennemsigtige containere, der indeholder en kodet nøgle, nøglens kodningsformat og dens kryptografiske algoritme.

Nøgler opnås normalt gennem nøglegeneratorer, certifikater eller nøglespecifikationer ved hjælp af en nøglefabrik.

Lad os oprette en symmetrisk Nøgle fra de medfølgende nøglebyte:

SecretKey secretKey = ny SecretKeySpec (keyBytes, "AES");

2.4. Initialisering af kryptering

Vi kalder i det() metode til at initialisere Cipher objekt med en Nøgle eller Certifikat og en opmode der angiver drifttilstanden for chifferet.

Valgfrit, vi kan passere i en kilde til tilfældighed. Som standard er a SecureRandom implementering af den højest prioriterede installerede udbyder anvendes. Ellers bruger den en kilde, der leveres af systemet.

Vi kan angive et sæt algoritmespecifikke parametre valgfrit. For eksempel kan vi videregive en IvParameterSpec til angiv en initialiseringsvektor.

Her er de tilgængelige krypteringsfunktioner:

  • ENCRYPT_MODE: initialiser kryptering modsætter sig krypteringstilstand
  • DECRYPT_MODE: initialiser kryptering modsætter sig dekrypteringstilstand
  • WRAP_MODE: initialiser kryptering modsætter sig nøgleindpakningstilstand
  • UNWRAP_MODE: initialiser kryptering modsætter sig tilstanden med nøgleudpakning

Lad os initialisere Kryptering objekt:

Cipher cipher = Cipher.getInstance ("AES / ECB / PKCS5Padding"); SecretKey secretKey = ny SecretKeySpec (keyBytes, "AES"); cipher.init (Cipher.ENCRYPT_MODE, secretKey); // ...

Nu, den i det metode kaster en InvalidKeyException hvis den medfølgende nøgle er upassende til initialisering af chifferet, som når en nøgellængde / kodning er ugyldig.

Det kastes også, når chifferet kræver visse algoritmeparametre, der ikke kan bestemmes ud fra nøglen, eller hvis nøglen har en nøglestørrelse, der overstiger den maksimalt tilladte nøglestørrelse (bestemt ud fra de konfigurerede JCE-jurisdiktionspolitiske filer).

Lad os se på et eksempel ved hjælp af en Certifikat:

offentlig byte [] encryptMessage (byte [] besked, certifikatcertifikat) kaster InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException {Cipher cipher = Cipher.getInstance ("RSA / ECB / PKCS1Padding"); cipher.init (Cipher.ENCRYPT_MODE, certifikat); // ...}

Det Kryptering objekt får den offentlige nøgle til datakryptering fra certifikatet ved at ringe til getPublicKey metode.

2.5. Kryptering og dekryptering

Efter initialisering af Kryptering objekt, vi kalder doFinal () metode til at udføre kryptering eller dekryptering. Denne metode returnerer et byte-array, der indeholder den krypterede eller dekrypterede meddelelse.

Det doFinal () metoden nulstiller også Kryptering gøre indsigelse mod den tilstand, den var i, da den tidligere blev initialiseret via et opkald til i det() metode, hvilket gør Kryptering objekt til rådighed til at kryptere eller dekryptere yderligere meddelelser.

Lad os ringe doFinal i vores encryptMessage metode:

offentlig byte [] encryptMessage (byte [] besked, byte [] keyBytes) kaster InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException, BadPaddingException, IllegalBlockSizeException {Cipher cipher = Cipher.getInstance ("AES5 / ECB SecretKey secretKey = ny SecretKeySpec (keyBytes, "AES"); cipher.init (Cipher.ENCRYPT_MODE, secretKey); return cipher.doFinal (besked); }

For at udføre en dekrypteringsoperation ændrer vi opmode til DECRYPT_MODE:

offentlig byte [] decryptMessage (byte [] encryptedMessage, byte [] keyBytes) kaster NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {Cipher cipher = Cipher.getInstance ("APS /") SecretKey secretKey = ny SecretKeySpec (keyBytes, "AES"); cipher.init (Cipher.DECRYPT_MODE, secretKey); return cipher.doFinal (encryptedMessage); }

2.6. Udbydere

Designet til at bruge en udbyderbaseret arkitektur, JCE tillader, at kvalificerede kryptografibiblioteker som BouncyCastle tilsluttes som sikkerhedsudbydere og nye algoritmer tilføjes problemfrit.

Lad os nu tilføje BouncyCastle som sikkerhedsudbyder. Vi kan tilføje en sikkerhedsudbyder enten statisk eller dynamisk.

For at tilføje BouncyCastle statisk ændrer vi java.sikkerhed fil placeret i / jre / lib / sikkerhed folder.

Vi tilføjer linjen i slutningen af ​​listen:

... security.provider.4 = com.sun.net.ssl.internal.ssl.Provider security.provider.5 = com.sun.crypto.provider.SunJCE security.provider.6 = sun.security.jgss.SunProvider security.provider.7 = org.bouncycastle.jce.provider.BouncyCastleProvider

Når du tilføjer udbyderegenskaben, er ejendomsnøglen i formatet sikkerhed.udbyder.N hvor nummeret N er en mere end den sidste på listen.

Vi kan også tilføje BouncyCastle-sikkerhedsudbyderen dynamisk uden at skulle ændre sikkerhedsfilen:

Security.addProvider (ny BouncyCastleProvider ());

Vi kan nu specificere udbyderen under chifferinitialisering:

Cipher cipher = Cipher.getInstance ("AES / ECB / PKCS5Padding", "BC");

F.Kr. angiver BouncyCastle som udbyder. Vi kan få listen over registrerede udbydere via Security.getProviders () metode.

3. Test af kryptering og dekryptering

Lad os skrive en eksemplet test for at illustrere meddelelseskryptering og dekryptering.

I denne test bruger vi AES-krypteringsalgoritme med en 128-bit nøgle og hævder, at det dekrypterede resultat er lig med den oprindelige meddelelsestekst:

@Test offentlig ugyldig nårIsEncryptedAndDecrypted_thenDecryptedEqualsOriginal () kaster Undtagelse {String encryptionKeyString = "thisisa128bitkey"; String originalMessage = "Dette er en hemmelig besked"; byte [] encryptionKeyBytes = encryptionKeyString.getBytes (); Cipher cipher = Cipher.getInstance ("AES / ECB / PKCS5Padding"); SecretKey secretKey = nye SecretKeySpec (encryptionKeyBytes, "AES"); cipher.init (Cipher.ENCRYPT_MODE, secretKey); byte [] encryptedMessageBytes = cipher.doFinal (message.getBytes ()); cipher.init (Cipher.DECRYPT_MODE, secretKey); byte [] decryptedMessageBytes = cipher.doFinal (encryptedMessageBytes); assertThat (originalMessage) .isEqualTo (ny streng (dekrypteretMessageBytes)); }

4. Konklusion

I denne artikel diskuterede vi Kryptering klasse og præsenterede brugseksempler. Flere detaljer om Kryptering klasse og JCE Framework findes i klassedokumentationen og Java Cryptography Architecture (JCA) Reference Guide.

Implementering af alle disse eksempler og kodestykker kan findes over på GitHub. Dette er et Maven-baseret projekt, så det skal være let at importere og køre som det er.