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

Java使用AES加密和解密的實例詳解

 更新時間:2017年07月12日 10:30:01   投稿:lqh  
這篇文章主要介紹了Java使用AES加密和解密的實例詳解的相關(guān)資料,需要的朋友可以參考下

Java使用AES加密和解密的實例詳解

前言:

AES的基本要求是,采用對稱分組密碼體制,密鑰長度的最少支持為128、192、256,分組長度128位,算法應(yīng)易于各種硬件和軟件實現(xiàn)。1998年NIST開始AES第一輪分析、測試和征集,共產(chǎn)生了15個候選算法。1999年3月完成了第二輪AES2的分析、測試。2000年10月2日美國政府正式宣布選中比利時密碼學(xué)家Joan Daemen 和 Vincent Rijmen 提出的一種密碼算法RIJNDAEL 作為 AES.   在應(yīng)用方面,盡管DES在安全上是脆弱的,但由于快速DES芯片的大量生產(chǎn),使得DES仍能暫時繼續(xù)使用,為提高安全強(qiáng)度,通常使用獨(dú)立密鑰的三級DES。但是DES遲早要被AES代替。流密碼體制較之分組密碼在理論上成熟且安全,但未被列入下一代加密標(biāo)準(zhǔn)。   

AES加密數(shù)據(jù)塊和密鑰長度可以是128比特、192比特、256比特中的任意一個。

AES加密有很多輪的重復(fù)和變換。大致步驟如下:

1、密鑰擴(kuò)展(KeyExpansion),
2、初始輪(Initial Round),
3、重復(fù)輪(Rounds),每一輪又包括:SubBytes、ShiftRows、MixColumns、AddRoundKey,
4、最終輪(Final Round),最終輪沒有MixColumns。

AES是一種對稱的加密算法,可基于相同的密鑰進(jìn)行加密和解密。Java采用AES算法進(jìn)行加解密的邏輯大致如下:

1、生成/獲取密鑰

2、加/解密 

1.1生成密鑰

密鑰的生成是通過KeyGenerator來生成的。通過獲取一個KeyGenerator實例,然后調(diào)用其generateKey()方法即可生成一個SecretKey對象。大致邏輯一般如下:

private SecretKey geneKey() throws Exception { 
  //獲取一個密鑰生成器實例 
  KeyGenerator keyGenerator = KeyGenerator.getInstance(ALGORITHM); 
  SecureRandom random = new SecureRandom(); 
  random.setSeed("123456".getBytes());//設(shè)置加密用的種子,密鑰 
  keyGenerator.init(random); 
  SecretKey secretKey = keyGenerator.generateKey(); 
  return secretKey; 
} 

上述生成密鑰的過程中指定了固定的種子,每次生成出來的密鑰都是一樣的。還有一種形式,我們可以通過不指定SecureRandom對象的種子,即不調(diào)用其setSeed方法,這樣每次生成出來的密鑰都可能是不一樣的。

private SecretKey geneKey() throws Exception { 
  //獲取一個密鑰生成器實例 
  KeyGenerator keyGenerator = KeyGenerator.getInstance(ALGORITHM); 
  SecureRandom random = new SecureRandom(); 
  keyGenerator.init(random); 
  SecretKey secretKey = keyGenerator.generateKey(); 
  return secretKey; 
} 

通過KeyGenerator的init(keySize)方法進(jìn)行初始化,而不是通過傳遞SecureRandom對象進(jìn)行初始化也可以達(dá)到上面的效果,每次生成的密鑰都可能是不一樣的。但是對應(yīng)的keySize的指定一定要正確,AES算法的keySize是128。

private SecretKey geneKey() throws Exception { 
  //獲取一個密鑰生成器實例 
  KeyGenerator keyGenerator = KeyGenerator.getInstance(ALGORITHM); 
  keyGenerator.init(128); 
  SecretKey secretKey = keyGenerator.generateKey(); 
  return secretKey; 
} 

但是這種每次生成出來的密鑰都是不同的情況下,我們需要把加密用的密鑰存儲起來,以供解密的時候使用,不然就沒法進(jìn)行解密了。 

1.2密鑰的存儲

密鑰SecretKey里面最核心的內(nèi)容就是其中的密鑰對應(yīng)的字節(jié)數(shù)組,可以通過SecretKey的getEncoded()方法獲取。然后把它存儲起來即可。最簡單的方式就是直接寫入一個文件中。

//把上面的密鑰存起來 
Path keyPath = Paths.get("D:/aes.key"); 
Files.write(keyPath, secretKey.getEncoded()); 

1.3獲取存儲的密鑰

獲取存儲的密鑰的核心是把密鑰的字節(jié)數(shù)組轉(zhuǎn)換為對應(yīng)的SecretKey。這可以通過SecretKeySpec來獲取,其實現(xiàn)了SecretKey接口,然后構(gòu)造參數(shù)里面將接收密鑰的字節(jié)數(shù)組。

private SecretKey readKey(Path keyPath) throws Exception { 
  //讀取存起來的密鑰 
  byte[] keyBytes = Files.readAllBytes(keyPath); 
  SecretKeySpec keySpec = new SecretKeySpec(keyBytes, ALGORITHM); 
  return keySpec; 
} 

1.4加解密

Java采用AES算法進(jìn)行加解密的過程是類似的,具體如下:

1、指定算法,獲取一個Cipher實例對象

Cipher cipher = Cipher.getInstance(ALGORITHM);//算法是AES 

2、生成/讀取用于加解密的密鑰

SecretKey secretKey = this.geneKey(); 

3、用指定的密鑰初始化Cipher對象,同時指定加解密模式,是加密模式還是解密模式。

cipher.init(Cipher.ENCRYPT_MODE, secretKey); 

4、通過update指定需要加密的內(nèi)容,不可多次調(diào)用。

cipher.update(content.getBytes()); 

5、通過Cipher的dofinal()進(jìn)行最終的加解密操作。

byte[] result = cipher.doFinal();//加密后的字節(jié)數(shù)組 

通過以上幾步就完成了使用AES算法進(jìn)行加解密的操作了。其實第4、5步是可以合在一起的,即在進(jìn)行doFinal的時候傳遞需要進(jìn)行加解密的內(nèi)容。但是如果update指定了加密的內(nèi)容,而doFinal的時候也指定了加密的內(nèi)容,那最終加密出來的結(jié)果將是兩次指定的加密內(nèi)容的和對應(yīng)的加密結(jié)果。

byte[] result = cipher.doFinal(content.getBytes()); 

以下是一次加解密操作的完整示例。

public class AESTest { 
 
  private static final String ALGORITHM = "AES"; 
   
  /** 
   * 生成密鑰 
   * @return 
   * @throws Exception 
   */ 
  private SecretKey geneKey() throws Exception { 
    //獲取一個密鑰生成器實例 
    KeyGenerator keyGenerator = KeyGenerator.getInstance(ALGORITHM); 
    SecureRandom random = new SecureRandom(); 
    random.setSeed("123456".getBytes());//設(shè)置加密用的種子,密鑰 
    keyGenerator.init(random); 
    SecretKey secretKey = keyGenerator.generateKey(); 
    //把上面的密鑰存起來 
    Path keyPath = Paths.get("D:/aes.key"); 
    Files.write(keyPath, secretKey.getEncoded()); 
    return secretKey; 
  } 
   
  /** 
   * 讀取存儲的密鑰 
   * @param keyPath 
   * @return 
   * @throws Exception 
   */ 
  private SecretKey readKey(Path keyPath) throws Exception { 
    //讀取存起來的密鑰 
    byte[] keyBytes = Files.readAllBytes(keyPath); 
    SecretKeySpec keySpec = new SecretKeySpec(keyBytes, ALGORITHM); 
    return keySpec; 
  } 
   
  /** 
   * 加密測試 
   */ 
  @Test 
  public void testEncrypt() throws Exception { 
    //1、指定算法、獲取Cipher對象 
    Cipher cipher = Cipher.getInstance(ALGORITHM);//算法是AES 
    //2、生成/讀取用于加解密的密鑰 
    SecretKey secretKey = this.geneKey(); 
    //3、用指定的密鑰初始化Cipher對象,指定是加密模式,還是解密模式 
    cipher.init(Cipher.ENCRYPT_MODE, secretKey); 
    String content = "Hello AES";//需要加密的內(nèi)容 
    //4、更新需要加密的內(nèi)容 
    cipher.update(content.getBytes()); 
    //5、進(jìn)行最終的加解密操作 
    byte[] result = cipher.doFinal();//加密后的字節(jié)數(shù)組 
    //也可以把4、5步組合到一起,但是如果保留了4步,同時又是如下這樣使用的話,加密的內(nèi)容將是之前update傳遞的內(nèi)容和doFinal傳遞的內(nèi)容的和。 
//   byte[] result = cipher.doFinal(content.getBytes()); 
    String base64Result = Base64.getEncoder().encodeToString(result);//對加密后的字節(jié)數(shù)組進(jìn)行Base64編碼 
    System.out.println("Result: " + base64Result); 
  } 
   
  /** 
   * 解密測試 
   */ 
  @Test 
  public void testDecrpyt() throws Exception { 
    Cipher cipher = Cipher.getInstance(ALGORITHM); 
    SecretKey secretKey = this.geneKey(); 
    cipher.init(Cipher.DECRYPT_MODE, secretKey); 
    String content = "pK9Xw4zqTMXYraDadSGJE3x/ftrDxIg2AM/acq0uixA=";//經(jīng)過Base64加密的待解密的內(nèi)容 
    byte[] encodedBytes = Base64.getDecoder().decode(content.getBytes()); 
    byte[] result = cipher.doFinal(encodedBytes);//對加密后的字節(jié)數(shù)組進(jìn)行解密 
    System.out.println("Result: " + new String(result)); 
  } 
   
} 

1.5使用存儲的密鑰進(jìn)行加解密示例

@Test 
public void test() throws Exception { 
  Cipher cipher = Cipher.getInstance(ALGORITHM); 
  KeyGenerator keyGenerator = KeyGenerator.getInstance(ALGORITHM); 
  keyGenerator.init(128); 
  SecretKey secretKey = keyGenerator.generateKey(); 
  //把上面的密鑰存起來 
  Path keyPath = Paths.get("D:/aes.key"); 
  Files.write(keyPath, secretKey.getEncoded()); 
   
  //讀取存起來的密鑰 
  SecretKey key = this.readKey(keyPath); 
  cipher.init(Cipher.ENCRYPT_MODE, key); 
  cipher.update("Hello World".getBytes()); 
  //密文 
  byte[] encryptBytes = cipher.doFinal(); 
  System.out.println(Base64.getEncoder().encodeToString(encryptBytes)); 
   
  //用取出來的密鑰進(jìn)行解密 
  cipher.init(Cipher.DECRYPT_MODE, key); 
  //明文 
  byte[] decryptBytes = cipher.doFinal(encryptBytes); 
  System.out.println(new String(decryptBytes)); 
} 

在上面的示例中,我們先生成了一個密鑰,然后把它保存到本地文件中,然后再把它讀出來,分別用以加密和解密。而且我們加密和解密都是用的同一個Cipher對象,但是在使用前需要重新通過init方法初始化加解密模式。 

感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!

相關(guān)文章

  • Java+opencv3.2.0實現(xiàn)hough圓檢測功能

    Java+opencv3.2.0實現(xiàn)hough圓檢測功能

    這篇文章主要為大家詳細(xì)介紹了Java+opencv3.2.0實現(xiàn)hough圓檢測,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-02-02
  • 探究Java常量本質(zhì)及三種常量池(小結(jié))

    探究Java常量本質(zhì)及三種常量池(小結(jié))

    這篇文章主要介紹了探究Java常量本質(zhì)及三種常量池(小結(jié)),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • springboot 如何重定向redirect 并隱藏參數(shù)

    springboot 如何重定向redirect 并隱藏參數(shù)

    這篇文章主要介紹了springboot 如何重定向redirect 并隱藏參數(shù)的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • Java中Instant的使用及轉(zhuǎn)換

    Java中Instant的使用及轉(zhuǎn)換

    Instant是java.time包中的一個類,本文主要介紹了Java中Instant的使用及轉(zhuǎn)換,具有一定的參考價值,感興趣的可以了解一下
    2024-06-06
  • spring-boot2.7.8添加swagger的案例詳解

    spring-boot2.7.8添加swagger的案例詳解

    這篇文章主要介紹了spring-boot2.7.8添加swagger的案例詳解,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2024-01-01
  • Java實戰(zhàn)之郵件的撰寫和發(fā)送

    Java實戰(zhàn)之郵件的撰寫和發(fā)送

    這篇文章主要為大家詳細(xì)介紹了通過Java代碼實現(xiàn)郵件的撰寫和發(fā)送功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,需要的小伙伴們可以學(xué)習(xí)一下
    2021-11-11
  • java高并發(fā)之理解進(jìn)程和線程

    java高并發(fā)之理解進(jìn)程和線程

    這篇文章主要給大家介紹了關(guān)于java高并發(fā)進(jìn)程和線程的內(nèi)容,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用java具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-10-10
  • springboot配置redis過程詳解

    springboot配置redis過程詳解

    這篇文章主要介紹了springboot配置redis過程詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-09-09
  • 分布式任務(wù)調(diào)度xxl-job問題解決

    分布式任務(wù)調(diào)度xxl-job問題解決

    這篇文章主要為大家介紹了分布式任務(wù)調(diào)度xxl-job的問題解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多多多進(jìn)步,早日升職加薪
    2022-03-03
  • WebDriver實現(xiàn)自動化打開IE中的google網(wǎng)頁并實現(xiàn)搜索

    WebDriver實現(xiàn)自動化打開IE中的google網(wǎng)頁并實現(xiàn)搜索

    這篇文章主要介紹了WebDriver實現(xiàn)自動化打開IE中的google網(wǎng)頁并實現(xiàn)搜索,需要的朋友可以參考下
    2014-04-04

最新評論