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

Java使用AES加密和解密的實(shí)例詳解

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

Java使用AES加密和解密的實(shí)例詳解

前言:

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

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

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

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

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

1、生成/獲取密鑰

2、加/解密 

1.1生成密鑰

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

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

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

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

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

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

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

1.2密鑰的存儲(chǔ)

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

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

1.3獲取存儲(chǔ)的密鑰

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

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

1.4加解密

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

1、指定算法,獲取一個(gè)Cipher實(shí)例對(duì)象

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

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

SecretKey secretKey = this.geneKey(); 

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

cipher.init(Cipher.ENCRYPT_MODE, secretKey); 

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

cipher.update(content.getBytes()); 

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

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

通過(guò)以上幾步就完成了使用AES算法進(jìn)行加解密的操作了。其實(shí)第4、5步是可以合在一起的,即在進(jìn)行doFinal的時(shí)候傳遞需要進(jìn)行加解密的內(nèi)容。但是如果update指定了加密的內(nèi)容,而doFinal的時(shí)候也指定了加密的內(nèi)容,那最終加密出來(lái)的結(jié)果將是兩次指定的加密內(nèi)容的和對(duì)應(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 { 
    //獲取一個(gè)密鑰生成器實(shí)例 
    KeyGenerator keyGenerator = KeyGenerator.getInstance(ALGORITHM); 
    SecureRandom random = new SecureRandom(); 
    random.setSeed("123456".getBytes());//設(shè)置加密用的種子,密鑰 
    keyGenerator.init(random); 
    SecretKey secretKey = keyGenerator.generateKey(); 
    //把上面的密鑰存起來(lái) 
    Path keyPath = Paths.get("D:/aes.key"); 
    Files.write(keyPath, secretKey.getEncoded()); 
    return secretKey; 
  } 
   
  /** 
   * 讀取存儲(chǔ)的密鑰 
   * @param keyPath 
   * @return 
   * @throws Exception 
   */ 
  private SecretKey readKey(Path keyPath) throws Exception { 
    //讀取存起來(lái)的密鑰 
    byte[] keyBytes = Files.readAllBytes(keyPath); 
    SecretKeySpec keySpec = new SecretKeySpec(keyBytes, ALGORITHM); 
    return keySpec; 
  } 
   
  /** 
   * 加密測(cè)試 
   */ 
  @Test 
  public void testEncrypt() throws Exception { 
    //1、指定算法、獲取Cipher對(duì)象 
    Cipher cipher = Cipher.getInstance(ALGORITHM);//算法是AES 
    //2、生成/讀取用于加解密的密鑰 
    SecretKey secretKey = this.geneKey(); 
    //3、用指定的密鑰初始化Cipher對(duì)象,指定是加密模式,還是解密模式 
    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步,同時(shí)又是如下這樣使用的話,加密的內(nèi)容將是之前update傳遞的內(nèi)容和doFinal傳遞的內(nèi)容的和。 
//   byte[] result = cipher.doFinal(content.getBytes()); 
    String base64Result = Base64.getEncoder().encodeToString(result);//對(duì)加密后的字節(jié)數(shù)組進(jìn)行Base64編碼 
    System.out.println("Result: " + base64Result); 
  } 
   
  /** 
   * 解密測(cè)試 
   */ 
  @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)過(guò)Base64加密的待解密的內(nèi)容 
    byte[] encodedBytes = Base64.getDecoder().decode(content.getBytes()); 
    byte[] result = cipher.doFinal(encodedBytes);//對(duì)加密后的字節(jié)數(shù)組進(jìn)行解密 
    System.out.println("Result: " + new String(result)); 
  } 
   
} 

1.5使用存儲(chǔ)的密鑰進(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(); 
  //把上面的密鑰存起來(lái) 
  Path keyPath = Paths.get("D:/aes.key"); 
  Files.write(keyPath, secretKey.getEncoded()); 
   
  //讀取存起來(lái)的密鑰 
  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)); 
   
  //用取出來(lái)的密鑰進(jìn)行解密 
  cipher.init(Cipher.DECRYPT_MODE, key); 
  //明文 
  byte[] decryptBytes = cipher.doFinal(encryptBytes); 
  System.out.println(new String(decryptBytes)); 
} 

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

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

相關(guān)文章

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    springboot配置redis過(guò)程詳解

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

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

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

    WebDriver實(shí)現(xiàn)自動(dòng)化打開(kāi)IE中的google網(wǎng)頁(yè)并實(shí)現(xiàn)搜索

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

最新評(píng)論