欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java AES加密和解密教程

 更新時間:2020年12月04日 14:49:05   作者:banq  
這篇文章主要介紹了Java AES加密和解密的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)Java,感興趣的朋友可以了解下

在本教程中,我們將看到如何使用JDK中的Java密碼體系結(jié)構(gòu)(JCA)來實現(xiàn)AES加密和解密。對稱密鑰塊密碼在數(shù)據(jù)加密中起重要作用。這意味著同一密鑰可用于加密和解密。高級加密標準(AES)是一種廣泛使用的對稱密鑰加密算法。

AES算法是一種迭代的對稱密鑰塊密碼,它支持128、192和256位的加密密鑰(秘密密鑰),以對128位的塊中的數(shù)據(jù)進行加密和解密。

在AES中生成密鑰的方法有兩種:從隨機數(shù)生成或從給定密碼生成。

在第一種方法中,應(yīng)該從像SecureRandom類這樣的加密安全(偽)隨機數(shù)生成器生成秘密密鑰。為了生成密鑰,我們可以使用KeyGenerator類。讓我們定義一種用于生成大小為n(128、192和256)位的AES密鑰的方法:

public static SecretKey generateKey(int n) throws NoSuchAlgorithmException {
    KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
    keyGenerator.init(n);
    SecretKey key = keyGenerator.generateKey();
    return key;
}

在第二種方法中,可以使用基于密碼的密鑰派生功能(例如PBKDF2)從給定的密碼派生AES秘密密鑰。下面方法可通過65,536次迭代和256位密鑰長度從給定密碼生成AES密鑰:

public static SecretKey getKeyFromPassword(String password, String salt)
    throws NoSuchAlgorithmException, InvalidKeySpecException {
    
    SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
    KeySpec spec = new PBEKeySpec(password.toCharArray(), salt.getBytes(), 65536, 256);
    SecretKey secret = new SecretKeySpec(factory.generateSecret(spec)
        .getEncoded(), "AES");
    return secret;
}

加密字符串

要實現(xiàn)輸入字符串加密,我們首先需要根據(jù)上一節(jié)生成密鑰和初始化向量IV:

IV是偽隨機值,其大小與加密的塊相同。我們可以使用SecureRandom類生成隨機IV。

讓我們定義一種生成IV的方法:

public static IvParameterSpec generateIv() {
    byte[] iv = new byte[16];
    new SecureRandom().nextBytes(iv);
    return new IvParameterSpec(iv);
}

下一步,我們使用getInstance()方法從Cipher類創(chuàng)建一個實例。

此外,我們使用帶有秘密密鑰,IV和加密模式的init()方法配置密碼實例。最后,我們通過調(diào)用doFinal()方法對輸入字符串進行加密。此方法獲取輸入字節(jié)并以字節(jié)為單位返回密文:

public static String encrypt(String algorithm, String input, SecretKey key,
    IvParameterSpec iv) throws NoSuchPaddingException, NoSuchAlgorithmException,
    InvalidAlgorithmParameterException, InvalidKeyException,
    BadPaddingException, IllegalBlockSizeException {
    
    Cipher cipher = Cipher.getInstance(algorithm);
    cipher.init(Cipher.ENCRYPT_MODE, key, iv);
    byte[] cipherText = cipher.doFinal(input.getBytes());
    return Base64.getEncoder()
        .encodeToString(cipherText);
}

為了解密輸入字符串,我們可以使用DECRYPT_MODE初始化密碼來解密內(nèi)容:

public static String decrypt(String algorithm, String cipherText, SecretKey key,
    IvParameterSpec iv) throws NoSuchPaddingException, NoSuchAlgorithmException,
    InvalidAlgorithmParameterException, InvalidKeyException,
    BadPaddingException, IllegalBlockSizeException {
    
    Cipher cipher = Cipher.getInstance(algorithm);
    cipher.init(Cipher.DECRYPT_MODE, key, iv);
    byte[] plainText = cipher.doFinal(Base64.getDecoder()
        .decode(cipherText));
    return new String(plainText);
}

編寫一個用于加密和解密字符串輸入的測試方法:

@Test
void givenString_whenEncrypt_thenSuccess()
    throws NoSuchAlgorithmException, IllegalBlockSizeException, InvalidKeyException,
    BadPaddingException, InvalidAlgorithmParameterException, NoSuchPaddingException { 
    
    String input = "baeldung";
    SecretKey key = AESUtil.generateKey(128);
    IvParameterSpec ivParameterSpec = AESUtil.generateIv();
    String algorithm = "AES/CBC/PKCS5Padding";
    String cipherText = AESUtil.encrypt(algorithm, input, key, ivParameterSpec);
    String plainText = AESUtil.decrypt(algorithm, cipherText, key, ivParameterSpec);
    Assertions.assertEquals(input, plainText);
}

加密文件

現(xiàn)在,讓我們使用AES算法加密文件。步驟是相同的​​,但是我們需要一些IO類來處理文件。讓我們加密一個文本文件:

public static void encryptFile(String algorithm, SecretKey key, IvParameterSpec iv,
    File inputFile, File outputFile) throws IOException, NoSuchPaddingException,
    NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException,
    BadPaddingException, IllegalBlockSizeException {
    
    Cipher cipher = Cipher.getInstance(algorithm);
    cipher.init(Cipher.ENCRYPT_MODE, key, iv);
    FileInputStream inputStream = new FileInputStream(inputFile);
    FileOutputStream outputStream = new FileOutputStream(outputFile);
    byte[] buffer = new byte[64];
    int bytesRead;
    while ((bytesRead = inputStream.read(buffer)) != -1) {
        byte[] output = cipher.update(buffer, 0, bytesRead);
        if (output != null) {
            outputStream.write(output);
        }
    }
    byte[] outputBytes = cipher.doFinal();
    if (outputBytes != null) {
        outputStream.write(outputBytes);
    }
    inputStream.close();
    outputStream.close();
}

請注意,不建議嘗試將整個文件(尤其是大文件)讀入內(nèi)存。相反,我們一次加密一個緩沖區(qū)。

為了解密文件,我們使用類似的步驟,并使用DECRYPT_MODE初始化密碼,如前所述。

再次,讓我們定義一個用于加密和解密文本文件的測試方法。在這種方法中,我們從測試資源目錄中讀取baeldung.txt文件,將其加密為一個名為baeldung.encrypted的文件,然后將該文件解密為一個新文件:

@Test
void givenFile_whenEncrypt_thenSuccess() 
    throws NoSuchAlgorithmException, IOException, IllegalBlockSizeException, 
    InvalidKeyException, BadPaddingException, InvalidAlgorithmParameterException, 
    NoSuchPaddingException {
    
    SecretKey key = AESUtil.generateKey(128);
    String algorithm = "AES/CBC/PKCS5Padding";
    IvParameterSpec ivParameterSpec = AESUtil.generateIv();
    Resource resource = new ClassPathResource("inputFile/baeldung.txt");
    File inputFile = resource.getFile();
    File encryptedFile = new File("classpath:baeldung.encrypted");
    File decryptedFile = new File("document.decrypted");
    AESUtil.encryptFile(algorithm, key, ivParameterSpec, inputFile, encryptedFile);
    AESUtil.decryptFile(
      algorithm, key, ivParameterSpec, encryptedFile, decryptedFile);
    assertThat(inputFile).hasSameTextualContentAs(decryptedFile);
}

基于密碼加密解密

我們可以使用從給定密碼派生的密鑰進行AES加密和解密。

為了生成密鑰,我們使用getKeyFromPassword()方法。加密和解密步驟與字符串輸入部分中顯示的步驟相同。然后,我們可以使用實例化的密碼和提供的密鑰來執(zhí)行加密。

讓我們寫一個測試方法:

@Test
void givenPassword_whenEncrypt_thenSuccess() 
    throws InvalidKeySpecException, NoSuchAlgorithmException, 
    IllegalBlockSizeException, InvalidKeyException, BadPaddingException, 
    InvalidAlgorithmParameterException, NoSuchPaddingException {
    
    String plainText = "www.baeldung.com";
    String password = "baeldung";
    String salt = "12345678";
    IvParameterSpec ivParameterSpec = AESUtil.generateIv();
    SecretKey key = AESUtil.getKeyFromPassword(password,salt);
    String cipherText = AESUtil.encryptPasswordBased(plainText, key, ivParameterSpec);
    String decryptedCipherText = AESUtil.decryptPasswordBased(
      cipherText, key, ivParameterSpec);
    Assertions.assertEquals(plainText, decryptedCipherText);
}

加密對象

為了加密Java對象,我們需要使用SealedObject類。該對象應(yīng)可序列化。讓我們從定義學(xué)生類開始:

public class Student implements Serializable {
    private String name;
    private int age;

    // standard setters and getters
}

接下來,讓我們加密Student對象:

public static SealedObject encryptObject(String algorithm, Serializable object,
    SecretKey key, IvParameterSpec iv) throws NoSuchPaddingException,
    NoSuchAlgorithmException, InvalidAlgorithmParameterException, 
    InvalidKeyException, IOException, IllegalBlockSizeException {
    
    Cipher cipher = Cipher.getInstance(algorithm);
    cipher.init(Cipher.ENCRYPT_MODE, key, iv);
    SealedObject sealedObject = new SealedObject(object, cipher);
    return sealedObject;
}

稍后可以使用正確的密碼解密加密的對象:

public static Serializable decryptObject(String algorithm, SealedObject sealedObject,
    SecretKey key, IvParameterSpec iv) throws NoSuchPaddingException,
    NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException,
    ClassNotFoundException, BadPaddingException, IllegalBlockSizeException,
    IOException {
    
    Cipher cipher = Cipher.getInstance(algorithm);
    cipher.init(Cipher.DECRYPT_MODE, key, iv);
    Serializable unsealObject = (Serializable) sealedObject.getObject(cipher);
    return unsealObject;
}

讓我們寫一個測試用例:

@Test
void givenObject_whenEncrypt_thenSuccess() 
    throws NoSuchAlgorithmException, IllegalBlockSizeException, InvalidKeyException,
    InvalidAlgorithmParameterException, NoSuchPaddingException, IOException, 
    BadPaddingException, ClassNotFoundException {
    
    Student student = new Student("Baeldung", 20);
    SecretKey key = AESUtil.generateKey(128);
    IvParameterSpec ivParameterSpec = AESUtil.generateIv();
    String algorithm = "AES/CBC/PKCS5Padding";
    SealedObject sealedObject = AESUtil.encryptObject(
      algorithm, student, key, ivParameterSpec);
    Student object = (Student) AESUtil.decryptObject(
      algorithm, sealedObject, key, ivParameterSpec);
    assertThat(student).isEqualToComparingFieldByField(object);
}

可以在GitHub上獲得本文的完整源代碼 。

以上就是Java AES加密和解密教程的詳細內(nèi)容,更多關(guān)于Java AES加密和解密的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java中classpath講解及使用方式

    Java中classpath講解及使用方式

    本文詳細講解了Java中classpath講解及使用方式,文中通過示例代碼介紹的非常詳細。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-12-12
  • Spring中常用注解的用法

    Spring中常用注解的用法

    這篇文章主要介紹了Spring中常用注解的用法,Spring注解方式減少了配置文件內(nèi)容,更加便于管理,并且使用注解可以大大提高了開發(fā)效率,注解本身是沒有功能的,和xml一樣,注解和xml都是一種元數(shù)據(jù),元數(shù)據(jù)即解釋數(shù)據(jù)的數(shù)據(jù),也就是所謂的配置,需要的朋友可以參考下
    2023-08-08
  • Java利用LocalDate進行日期處理的完全指南

    Java利用LocalDate進行日期處理的完全指南

    這篇文章主要為大家詳細介紹了Java利用LocalDate進行日期處理的詳細教程,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-03-03
  • 詳解Spring Cloud Zuul中路由配置細節(jié)

    詳解Spring Cloud Zuul中路由配置細節(jié)

    本篇文章主要介紹了詳解Spring Cloud Zuul中路由配置細節(jié),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-10-10
  • spring boot優(yōu)雅集成redisson詳解

    spring boot優(yōu)雅集成redisson詳解

    這篇文章主要為大家介紹了spring boot優(yōu)雅集成redisson詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-11-11
  • 基于java實現(xiàn)租車管理系統(tǒng)

    基于java實現(xiàn)租車管理系統(tǒng)

    這篇文章主要為大家詳細介紹了基于java實現(xiàn)租車管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-12-12
  • java sleep()和wait()的區(qū)別點總結(jié)

    java sleep()和wait()的區(qū)別點總結(jié)

    在本篇文章里小編給大家整理了一篇關(guān)于java sleep()和wait()的區(qū)別的相關(guān)內(nèi)容,有興趣的朋友們可以學(xué)習(xí)下。
    2021-04-04
  • JAVA實現(xiàn)漢字轉(zhuǎn)拼音功能代碼實例

    JAVA實現(xiàn)漢字轉(zhuǎn)拼音功能代碼實例

    這篇文章主要介紹了JAVA實現(xiàn)漢字轉(zhuǎn)拼音功能代碼實例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-05-05
  • springboot集成Mybatis-plus-join-boot-start詳解

    springboot集成Mybatis-plus-join-boot-start詳解

    這篇文章主要介紹了springboot集成Mybatis-plus-join-boot-start方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-04-04
  • 深入理解Swift中的Substring和String

    深入理解Swift中的Substring和String

    這篇文章主要給大家深入的介紹了Swift中Substring和String的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2018-03-03

最新評論