Java AES titkosítás és visszafejtés

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

A szimmetrikus kulcsú blokkos titkosítás fontos szerepet játszik az adatok titkosításában. Ez azt jelenti, hogy ugyanazt a kulcsot használják mind a titkosításhoz, mind a visszafejtéshez. Az Advanced Encryption Standard (AES) egy széles körben használt szimmetrikus kulcsú titkosítási algoritmus.

Ebben az oktatóanyagban megtudhatjuk, hogyan lehet az AES titkosítást és visszafejtést megvalósítani a JDK-ban lévő Java Cryptography Architecture (JCA) segítségével.

2. AES algoritmus

Az AES algoritmus egy iteratív, szimmetrikus kulcsú blokkos titkosítás támogatja a 128, 192 és 256 bites kriptográfiai kulcsokat (titkos kulcsokat) az adatok titkosításához és visszafejtéséhez 128 bites blokkokban. Az alábbi ábra a magas szintű AES algoritmust mutatja:

Ha a titkosítandó adatok nem felelnek meg a 128 bites blokkméret követelményének, akkor azt ki kell tölteni. A kitöltés az utolsó blokk 128 bitesre való feltöltésének folyamata.

3. AES variációk

Az AES algoritmusnak hat működési módja van:

  1. EKB (elektronikus kódkönyv)
  2. CBC (Cipher Block Chaining)
  3. CFB (Cipher FeedBack)
  4. OFB (kimeneti visszacsatolás)
  5. CTR (számláló)
  6. GCM (Galois / Számláló mód)

A működési mód alkalmazható a titkosítási algoritmus hatásának erősítése érdekében. Ezenkívül a működési mód átalakíthatja a blokk titkosítást stream titkosítássá. Minden módnak megvan a maga ereje és gyengesége. Nézzünk át gyorsan.

3.1. EKB

Ez a működési mód a legegyszerűbb. A sima szöveg 128 bit méretű blokkokra van osztva. Ezután minden blokkot ugyanazzal a kulccsal és algoritmussal titkosítunk. Ezért ugyanarra a blokkra ugyanazt az eredményt adja. Ez a mód fő gyengesége és titkosításhoz nem ajánlott. Kitöltési adatokat igényel.

3.2. CBC

Az EKB gyengeségének leküzdése érdekében a CBC mód inicializáló vektort (IV) használ a titkosítás bővítésére. Először is, a CBC a sima szövegblokkot használja xor a IV-vel. Ezután titkosítja az eredményt a rejtjeles szövegblokkba. A következő blokkban a titkosítási eredményt használja a sima szövegblokkal az utolsó blokkig.

Ebben a módban a titkosítás nem párhuzamos, de a visszafejtés párhuzamos. Ez is kitöltési adatokat igényel.

3.3. CFB

Ez az üzemmód stream-rejtjelként használható. Először titkosítja az IV-t, majd a sima szöveg blokkjának megszerzéséhez xor-t használ a sima szöveg blokkhoz. Ezután a CFB titkosítja a titkosítási eredményt a sima szöveg xorára. Szüksége van egy IV.

Ebben a módban a visszafejtés párhuzamosítható, de a titkosítás nem párhuzamos.

3.4. OFB

Ez a mód stream-rejtjelként használható. Először is titkosítja a IV. Ezután a titkosítási eredményeket használja a sima szöveg megszerzésére a rejtjeles szöveg megszerzéséhez.

Nem igényel kitöltési adatokat, és a zajos blokk nem fogja befolyásolni.

3.5. CTR

Ez a mód a számláló értékét használja IV-ként. Nagyon hasonlít az OFB-hez, de a számlálót minden alkalommal titkosításra használja a IV helyett.

Ennek a módnak két erőssége van, beleértve a titkosítás / visszafejtés párhuzamosítását, és az egyik blokkban lévő zaj nem befolyásolja a többi blokkot.

3.6. GCM

Ez az üzemmód a CTR mód kiterjesztése. A GCM jelentős figyelmet kapott, és a NIST javasolja. A GCM modell titkosított szöveget és hitelesítési címkét ad ki. Ennek a módnak a fő előnye az algoritmus többi működési módjához képest a hatékonysága.

Ebben az oktatóanyagban a AES / CBC / PKCS5Padding algoritmus, mert sok projektben széles körben használják.

3.7. Az adatok mérete a titkosítás után

Mint korábban említettük, az AES blokkmérete 128 bit vagy 16 bájt. Az AES nem változtatja meg a méretet, és a titkosított szöveg mérete megegyezik a tiszta szöveg méretével. Ezenkívül az EKB és a CBC módban használnunk kell egy párnázási algoritmust PKCS 5. Tehát az adatok mérete a titkosítás után:

rejtjelezett_méret (bájt) = tiszta szöveg_méret + (16 - (tiszta szöveg_méret% 16))

Az IV titkosított szöveggel történő tárolásához további 16 bájtot kell hozzáadnunk.

4. AES paraméterek

Az AES algoritmusban három paraméterre van szükségünk: bemeneti adatok, titkos kulcs és IV. A IV-et nem EKB-módban használják.

4.1. Beviteli adat

Az AES bemeneti adatai lehetnek karakterlánc, fájl, objektum és jelszó alapúak.

4.2. Titkos kulcs

Kétféle módon lehet titkos kulcsot előállítani az AES-ben: véletlen számból generálni vagy adott jelszóból levezetni.

Első megközelítésben a titkos kulcsot egy kriptográfiailag biztonságos (ál) véletlenszám-generátorból kell létrehozni, mint például SecureRandom osztály.

Titkos kulcs előállításához használhatjuk a KeyGenerator osztály. Határozzunk meg egy módszert az AES kulcs előállítására a méretével n (128, 192 és 256) bitek:

public static SecretKey generatorKey (int n) NoSuchAlgorithmException {KeyGenerator keyGenerator = KeyGenerator.getInstance ("AES") dob; keyGenerator.init (n); SecretKey kulcs = keyGenerator.generateKey (); visszatérési kulcs; }

A második megközelítésben az AES titkos kulcs egy adott jelszóból származtatható egy olyan jelszóalapú kulcs levezetési függvény segítségével, mint a PBKDF2. Sóértékre is szükségünk van ahhoz, hogy a jelszót titkos kulccsá alakítsuk. A só szintén véletlenszerű érték.

Használhatjuk a SecretKeyFactory osztály a PBKDF2WithHmacSHA256 algoritmus kulcs generálásához egy adott jelszóból.

Határozzunk meg egy módszert az AES kulcs előállítására egy adott jelszóból 65 536 iterációval és 256 bites kulcshosszal:

public static SecretKey getKeyFromPassword (karakterlánc jelszó, karakterlánc só) dobja a NoSuchAlgorithmException, InvalidKeySpecException {SecretKeyFactory factory = SecretKeyFactory.getInstance ("PBKDF2WithHmacSHA256"); KeySpec spec = new PBEKeySpec (jelszó.toCharArray (), salt.getBytes (), 65536, 256); SecretKey secret = új SecretKeySpec (gyár.generateSecret (spec) .getEncoded (), "AES"); visszatérési titok; }

4.3. Inicializálási vektor (IV)

A IV ál-véletlenszerű érték, és ugyanolyan méretű, mint a titkosított blokk. Használhatjuk a SecureRandom osztály véletlenszerű generálásához IV.

Határozzunk meg egy módszert egy IV előállítására:

public static IvParameterSpec generálIv () {byte [] iv = új byte [16]; új SecureRandom (). nextBytes (iv); return new IvParameterSpec (iv); }

5. Titkosítás és visszafejtés

5.1. Húr

A bemeneti karakterlánc-titkosítás megvalósításához először elő kell állítanunk a titkos kulcsot és az IV-et az előző szakasz szerint. Következő lépésként létrehozunk egy példányt a Rejtjel osztály a getInstance () módszer.

Ezenkívül egy titkosító példányt konfigurálunk a benne() módszer titkos kulccsal, IV és titkosítási móddal. Végül a bemeneti karakterláncot kódoljuk a doFinal () módszer. Ez a módszer megkapja a bemeneti bájtokat, és visszaadja a titkosított szöveget bájtokban:

public static String encrypt (karakterlánc-algoritmus, karakterlánc-bevitel, SecretKey-kulcs, IvParameterSpec iv) dobja a NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, BadPizeignalxxception cipher.init (Cipher.ENCRYPT_MODE, kulcs, iv); byte [] cipherText = cipher.doFinal (input.getBytes ()); return Base64.getEncoder () .encodeToString (cipherText); }

Egy bemeneti karakterlánc visszafejtéséhez inicializálhatjuk a rejtjelünket a DECRYPT_MODE a tartalom visszafejtése:

nyilvános statikus karakterlánc visszafejtése (karakterlánc-algoritmus, String cipherText, SecretKey kulcs, IvParameterSpec iv) dobja a NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyExlegception = BadPadget (BadPadgetx) cipher.init (Cipher.DECRYPT_MODE, kulcs, iv); byte [] plainText = cipher.doFinal (Base64.getDecoder () .decode (cipherText)); return new String (plainText); }

Írjunk egy tesztmódszert egy karakterlánc bemenet titkosításához és visszafejtéséhez:

@Test void givenString_whenEncrypt_thenSuccess () dobja a NoSuchAlgorithmException, IllegalBlockSizeException, InvalidKeyException, BadPaddingException, InvalidAlgorithmParameterException, NoSuchPeldung; NoSuchPadding; SecretKey kulcs = AESUtil.generateKey (128); IvParameterSpec ivParameterSpec = AESUtil.generateIv (); Karakterlánc-algoritmus = "AES / CBC / PKCS5Padding"; String cipherText = AESUtil.encrypt (algoritmus, input, kulcs, ivParameterSpec); String plainText = AESUtil.decrypt (algoritmus, cipherText, kulcs, ivParameterSpec); Assertions.assertEquals (input, plainText); }

5.2. File

Most titkosítsunk egy fájlt az AES algoritmus segítségével. A lépések ugyanazok, de szükségünk van néhányra IO osztályok dolgozni a fájlokat. Titkosítsunk egy szöveges fájlt:

public static void encryptFile (Karakterlánc algoritmus, SecretKey kulcs, IvParameterSpec iv, File inputFile, File outputFile) az IOException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException cipher.init (Cipher.ENCRYPT_MODE, kulcs, iv); FileInputStream inputStream = új FileInputStream (inputFile); FileOutputStream outputStream = új FileOutputStream (outputFile); bájt [] puffer = új bájt [64]; int bytesRead; while ((bytesRead = inputStream.read (puffer))! = -1) {byte [] output = cipher.update (puffer, 0, bytesRead); if (output! = null) {outputStream.write (output); }} bájt [] outputBytes = cipher.doFinal (); if (outputBytes! = null) {outputStream.write (outputBytes); } inputStream.close (); outputStream.close (); }

Felhívjuk figyelmét, hogy nem ajánlott a teljes fájlt memóriába olvasni - főleg ha nagy -. Ehelyett egy puffert kódolunk egyszerre.

A fájl dekódolásához hasonló lépéseket alkalmazunk, és a segítségével inicializáljuk a rejtjelünket DECRYPT_MODE mint azt korábban láttuk.

Ismét adjunk meg egy tesztelési módszert egy szöveges fájl titkosításához és visszafejtéséhez. Ebben a módszerben a baeldung.txt fájlt a teszt erőforrás könyvtárból, titkosítsa egy nevű fájlba baeldung.titkosítva, majd dekódolja a fájlt egy új fájlba:

A @Test void givenFile_whenEncrypt_thenSuccess () dobja a NoSuchAlgorithmException, IOException, IllegalBlockSizeException, InvalidKeyException, BadPaddingException, InvalidAlgorithmParameterException Noilt Karakterlánc-algoritmus = "AES / CBC / PKCS5Padding"; IvParameterSpec ivParameterSpec = AESUtil.generateIv (); Erőforrás = új ClassPathResource ("inputFile / baeldung.txt"); Fájl inputFile = resource.getFile (); File encryptedFile = new File ("classpath: baeldung.encrypted"); File decryptedFile = new File ("document.decrypted"); AESUtil.encryptFile (algoritmus, kulcs, ivParameterSpec, inputFile, encryptedFile); AESUtil.decryptFile (algoritmus, kulcs, ivParameterSpec, encryptedFile, decryptedFile); assertThat (inputFile) .hasSameTextualContentAs (decryptedFile); }

5.3. Jelszó alapú

Az AES titkosítást és visszafejtést megtehetjük egy titkos kulcs segítségével, amely egy adott jelszóból származik.

Titkos kulcs előállításához a getKeyFromPassword () módszer. A titkosítási és a visszafejtési lépések megegyeznek a karakterlánc beviteli szakaszban bemutatottakkal. Ezután a példányosított titkosítást és a mellékelt titkos kulcsot használhatjuk a titkosítás végrehajtására.

Írjunk egy tesztmódszert:

@Test void givenPassword_whenEncrypt_thenSuccess () InvalidKeySpecException, NoSuchAlgorithmException, IllegalBlockSizeException, InvalidKeyException, BadPaddingException, InvalidAlgorithmParam; InvalidAlgorithmParam; Karakterlánc jelszó = "baeldung"; Vonósó = "12345678"; IvParameterSpec ivParameterSpec = AESUtil.generateIv (); SecretKey kulcs = AESUtil.getKeyFromPassword (jelszó, só); String cipherText = AESUtil.encryptPasswordBased (plainText, kulcs, ivParameterSpec); String decryptedCipherText = AESUtil.decryptPasswordBased (cipherText, kulcs, ivParameterSpec); Assertions.assertEquals (plainText, decryptedCipherText); }

5.4. Tárgy

Java objektum titkosításához a SealedObject osztály. Az objektum legyen Sorosítható. Kezdjük azzal, hogy meghatározzuk a Diák osztály:

public class A diák végrehajtja a Serializable {private String name; privát int kor; // szabványos beállítók és szerelők} 

Ezután titkosítsuk a Diák tárgy :

public static SealedObject encryptObject (Karakterlánc algoritmus, Serializálható objektum, SecretKey kulcs, IvParameterSpec iv) dobja a NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyExcet, InvalidKeyException, cipher.init (Cipher.ENCRYPT_MODE, kulcs, iv); SealedObject sealedObject = új SealedObject (objektum, rejtjel); return sealedObject; }

A titkosított objektum később visszafejthető a helyes rejtjel használatával:

public static Serializable decryptObject (String algoritmus, SealedObject sealedObject, titkos kulcsát kulcs, IvParameterSpec IV) dob NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, ClassNotFoundException, BadPaddingException, IllegalBlockSizeException, IOException {Cipher titkosító = Cipher.getInstance (algoritmus); cipher.init (Cipher.DECRYPT_MODE, kulcs, iv); Serializable unsealObject = (Serializable) sealedObject.getObject (rejtjel); return unsealObject; }

Írjunk egy tesztesetet:

@Test void givenObject_whenEncrypt_thenSuccess () dob NoSuchAlgorithmException, IllegalBlockSizeException, InvalidKeyException, InvalidAlgorithmParameterException, NoSuchPaddingException, IOException, BadPaddingException, ClassNotFoundException {Student diák = új Student ( "Baeldung", 20); SecretKey kulcs = AESUtil.generateKey (128); IvParameterSpec ivParameterSpec = AESUtil.generateIv (); Karakterlánc-algoritmus = "AES / CBC / PKCS5Padding"; SealedObject sealedObject = AESUtil.encryptObject (algoritmus, tanuló, kulcs, ivParameterSpec); Student object = (Student) AESUtil.decryptObject (algoritmus, sealedObject, kulcs, ivParameterSpec); assertThat (hallgató) .isEqualToComparingFieldByField (objektum); }

6. Következtetés

Összefoglalva, megtanultuk, hogyan kell titkosítani és visszafejteni a bemeneti adatokat, például a karakterláncokat, fájlokat, objektumokat és jelszó alapú adatokat, a Java AES algoritmusának felhasználásával. Ezenkívül megvitattuk az AES variációit és az adatok méretét a titkosítás után.

Mint mindig, a cikk teljes forráskódja elérhető a GitHubon.

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