AES高級加密標準簡析

1 AES高級加密標準簡介

1.1 概述

  高級加密標準(英語:Advanced Encryption Standard,縮寫:AES),在密碼學中又稱Rijndael加密法,是美國聯邦政府採用的一種區塊加密標準。這個標準用來替代原先的DES,已經被多方分析且廣爲全世界所使用。通過五年的甄選流程,高級加密標準由美國國家標準與技術研究院(NIST)於2001年11月26日發佈於FIPS PUB 197,並在2002年5月26日成爲有效的標準。2006年,高級加密標準已然成爲對稱密鑰加密中最流行的算法之一。java

1.2 發展歷史

  1997年4月15日,美國ANSI發起徵集AES(advanced encryption standard)的活動,併爲此成立了AES工做小組。
  1997年9月12日,美國聯邦登記處公佈了正式徵集AES候選算法的通告。對AES的基本要求是: 比三重DES快、至少與三重DES同樣安全、數據分組長度爲128比特、密鑰長度爲128/192/256比特。
  1998年8月12日,在首屆AES候選會議(first AES candidate conference)上公佈了AES的15個候選算法,任由全世界各機構和我的攻擊和評論。
  1999年3月,在第2屆AES候選會議(second AES candidate conference)上通過對全球各密碼機構和我的對候選算法分析結果的討論,從15個候選算法中選出了5個。分別是RC六、Rijndael、SERPENT、Twofish和MARS。
  2000年4月13日至14日,召開了第3屆AES候選會議(third AES candidate conference),繼續對最後5個候選算法進行討論。
  2000年10月2日,NIST宣佈Rijndael做爲新的AES。通過3年多的討論,Rijndael終於脫穎而出。
  Rijndael由比利時的Joan Daemen和Vincent Rijmen設計。算法的原型是Square算法,它的設計策略是寬軌跡策略(wide trail strategy)。算法有很好的抵抗差分密碼分析及線性密碼分析的能力。

1.3 算法原理

  對稱密碼體制的發展趨勢將以分組密碼爲重點。分組密碼算法一般由 密鑰擴展算法和加密(解密)算法兩部分組成。密鑰擴展算法將b字節用戶主密鑰擴展成r個子密鑰。加密算法由一個密碼學上的弱函數f與r個子密鑰迭代r次組成。混亂和密鑰擴散是分組密碼算法設計的基本原則。抵禦已知明文的差分和線性攻擊,可變長密鑰和分組是該體制的設計要點。
  AES是美國國家標準技術研究所NIST旨在取代 DES的21世紀的加密標準。
  AES的基本要求是,採用對稱分組密碼體制,密鑰的長度最少支持爲12八、19二、256,分組長度128位,算法應易於各類硬件和軟件實現。1998年NIST開始AES第一輪分析、測試和徵集,共產生了15個候選算法。1999年3月完成了第二輪AES2的分析、測試。2000年10月2日美國政府正式宣佈選中 比利時密碼學家Joan Daemen 和 Vincent Rijmen 提出的一種密碼算法RIJNDAEL 做爲 AES.
  在應用方面,儘管DES在安全上是脆弱的,但因爲快速DES芯片的大量生產,使得DES仍能暫時繼續使用,爲提升安全強度,一般使用獨立密鑰的三級DES。可是DES早晚要被AES代替。流密碼體制較之分組密碼在理論上成熟且安全,但未被列入下一代加密標準。
  AES加密數據塊分組長度必須爲128比特,密鑰長度能夠是128比特、192比特、256比特中的任意一個(若是數據塊及密鑰長度不足時,會補齊)。AES加密有不少輪的重複和變換。大體步驟以下:一、密鑰擴展(KeyExpansion),二、初始輪(Initial Round),三、重複輪(Rounds),每一輪又包括:SubBytes、ShiftRows、MixColumns、AddRoundKey,四、最終輪(Final Round),最終輪沒有MixColumns。

1.4 算法應用

  高級加密標準AES(Rijndael)算法在各行業各部門中將得到普遍的應用,成爲虛擬專用網、SONET(同步光網絡)、遠程訪問服務器(RAS)、高速ATM/Ethernet路由器、移動通訊、衛星通訊、電子金融業務等的機密算法,並逐漸取代DES在IPSee、SSL和ATM中的使用。IEEE802.11i草案已經定義了AES加密的兩種不一樣運行模式,成功解決了無線局域網(WLAN)標準中的諸多安全問題。此外,得益於密碼技術的高速發展,政府及軍事通訊更多的採用高級的加密算法,以及網絡保密系統,財政保密、遊戲機密等方面AES加密算法都獲得了普遍的應用。

2 java代碼實現

  1 package xin.dreaming.aes;
  2 
  3 
  4 import javax.crypto.Cipher;
  5 import javax.crypto.SecretKey;
  6 import javax.crypto.spec.IvParameterSpec;
  7 import javax.crypto.spec.SecretKeySpec;
  8 
  9 import org.apache.commons.codec.binary.Base64;
 10 import org.junit.Test;
 11 public class AESUtils {
 12 
 13     /**
 14      * 生成隨機密鑰
 15      * 
 16      * @param size
 17      *            位數
 18      * @return
 19      */
 20     public static String generateRandomKey(int size) {
 21         StringBuilder key = new StringBuilder();
 22         String chars = "0123456789ABCDEF";
 23         for (int i = 0; i < size; i++) {
 24             int index = (int) (Math.random() * (chars.length() - 1));
 25             key.append(chars.charAt(index));
 26         }
 27         return key.toString();
 28     }
 29     
 30     /**
 31      * AES加密
 32      * 
 33      * @param plainBytes
 34      *            明文字節數組
 35      * @param keyBytes
 36      *            對稱密鑰字節數組
 37      * @param useBase64Code
 38      *            是否使用Base64編碼
 39      * @param charset
 40      *            編碼格式
 41      * @return byte[]
 42      */
 43     public static byte[] encryptAES(byte[] plainBytes, byte[] keyBytes, boolean useBase64Code, String charset) throws Exception {
 44         String cipherAlgorithm = "AES/CBC/PKCS5Padding";
 45         String keyAlgorithm = "AES";
 46         String IV = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
 47 
 48         try {
 49             Cipher cipher = Cipher.getInstance(cipherAlgorithm);
 50             SecretKey secretKey = new SecretKeySpec(keyBytes, keyAlgorithm);
 51             IvParameterSpec ivspec = new IvParameterSpec(IV.getBytes());
 52 
 53             cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivspec);
 54 
 55             byte[] encryptedBlock = cipher.doFinal(plainBytes);
 56 
 57             if (useBase64Code) {
 58                 return Base64.encodeBase64String(encryptedBlock).getBytes(charset);
 59             } else {
 60                 return encryptedBlock;
 61             }
 62         } catch (Exception e) {
 63             e.printStackTrace();
 64             throw new Exception("AES加密失敗");
 65         }
 66     }
 67 
 68     /**
 69      * AES解密
 70      * 
 71      * @param cryptedBytes
 72      *            密文字節數組
 73      * @param keyBytes
 74      *            對稱密鑰字節數組
 75      * @param useBase64Code
 76      *            是否使用Base64編碼
 77      * @param charset
 78      *            編碼格式
 79      * @return byte[]
 80      */
 81     public static byte[] decryptAES(byte[] cryptedBytes, byte[] keyBytes, boolean useBase64Code, String charset) throws Exception {
 82         String cipherAlgorithm = "AES/CBC/PKCS5Padding";
 83         String keyAlgorithm = "AES";
 84         String IV = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
 85 
 86         byte[] data = null;
 87 
 88         // 若是是Base64編碼的話,則要Base64解碼
 89         if (useBase64Code) {
 90             data = Base64.decodeBase64(new String(cryptedBytes, charset));
 91         } else {
 92             data = cryptedBytes;
 93         }
 94 
 95         try {
 96             Cipher cipher = Cipher.getInstance(cipherAlgorithm);
 97             SecretKey secretKey = new SecretKeySpec(keyBytes, keyAlgorithm);
 98             IvParameterSpec ivspec = new IvParameterSpec(IV.getBytes());
 99 
100             cipher.init(Cipher.DECRYPT_MODE, secretKey, ivspec);
101 
102             byte[] decryptedBlock = cipher.doFinal(data);
103 
104             return decryptedBlock;
105         } catch (Exception e) {
106             e.printStackTrace();
107             throw new Exception("AES解密失敗");
108         }
109     }
110     
111     /**
112      * BASE64加密
113      * 
114      * @param key
115      * @return
116      * @throws Exception
117      */
118 
119     
120     @Test
121     public void aesTest() throws Exception{
122         String value ="DREAMING.XIN";
123         //生成隨機AES對稱密鑰
124         String keyStr = generateRandomKey(16);
125         byte[] keyBytes = keyStr.getBytes("UTF-8");
126         
127         byte[] encryptAES = encryptAES(value.getBytes(), keyBytes, true, "UTF-8");
128         
129         System.out.println("AES加密後數據: "+new String(encryptAES));
130         
131         /*String encodeBase64String = Base64.encodeBase64String(encryptAES);
132         
133         System.out.println("先AES後BASE64: "+encodeBase64String);
134         
135         byte[] decodeBase64 = Base64.decodeBase64(encodeBase64String);*/
136         
137         byte[] decryptAES = decryptAES(encryptAES, keyBytes, true, "UTF-8");
138         
139         System.out.println("AES減密後數據: "+ new String(decryptAES));
140         
141     }
142     
143 }

運行結果:算法

參考:

  一、https://baike.baidu.com/item/aes/5903?fr=aladdin&fromid=3233272&fromtitle=aes%E5%8A%A0%E5%AF%86%E7%AE%97%E6%B3%95apache

相關文章
相關標籤/搜索