AES發展歷史
- 1997年NIST發起了整機替代DES算法的活動:高級數據加密標準(Advanced Encryption Standard);
- NIST要求算法比3DES塊,安全性高,具有128位分組長度,支持128、192、256位長度的密鑰;
- 2000年Rijndael算法當選AES算法標準;
- AES:密鑰建立時間短、靈敏性好、內存需求低,被廣泛應用;
- AES跟進密鑰長度分爲AES-128、AES-256幾種。
應用
AES是用來替代DES的,所以凡是使用DES的地方都應該優先考慮使用AES替換,DES作爲遺留系統或者學習保留,實際建議使用AES,一般場景AES-128即可,高安全場景可以使用AES-257,在JDK 6中若要使用256的加密方式,需要:無政策性限制權限文件。
Java中使用步驟
AES的使用和DES一樣,也是經過三步,Java的API封裝的很好,使用SPI機制實現策略模式,外部代碼改動很小。
在使用其他對稱加密算法:RC2、RC4、Blowfish算法的時候都可以參照下面的模式。
- 構建密鑰:使用KeyGenerator,這個步驟對稱加密算法和非對稱加密算法都需要;
- 構建AES專用的SecretKey:和DES和3DES不同,使用SecretKeySpec即可,這步是針對存儲下來的密鑰進行處理;
- 進行加解密:要注意設置Cipher的工作模式。
public class AESTest {
// private static final String CIPHER_ALGORITHM = "DESede";
private static final String CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding";
private static final String KEY_ALGORITHM = "AES";
public static void main(String[] args) throws Exception {
// 產生Key,一般只產生一次
byte[] key = generateKey();
String keyStr = Base64.getEncoder().encodeToString(key);
String input = "加密我";
// 加密數據
byte[] encryptData = encrypt(input.getBytes(), key);
// 解密數據
byte[] dencryData = decrypt(encryptData, key);
String msg = String.format("原始數據: %s , Key : %s , 加密數據: %s , 解密數據: %s", input, keyStr,
HexBin.encode(encryptData), new String(dencryData));
System.out.println(msg);
}
/**
* 產生符合要求的Key,如果不用KeyGenerator隨機性不好,而且要求自己對算法比較熟悉,能產生符合要求的Key
*
* @return
* @throws NoSuchAlgorithmException
*/
public static byte[] generateKey() throws NoSuchAlgorithmException {
KeyGenerator kg = KeyGenerator.getInstance(KEY_ALGORITHM);
// 3DES要求使用112或者168位密鑰
// kg.init(112);
kg.init(128);
SecretKey secretKey = kg.generateKey();
byte[] key = secretKey.getEncoded();
return key;
}
/**
* 獲取算法需要的安全密鑰,這步比DES和3DES簡單
*
* @param key
* @return
* @throws NoSuchAlgorithmException
* @throws InvalidKeyException
* @throws InvalidKeySpecException
*/
public static SecretKey getSecretKey(byte[] key)
throws NoSuchAlgorithmException, InvalidKeyException, InvalidKeySpecException {
SecretKey keySpec = new SecretKeySpec(key, KEY_ALGORITHM);
return keySpec;
}
/**
* 加密數據
*
* @param input
* @param key
* @return
* @throws Exception
*/
public static byte[] encrypt(byte[] input, byte[] key) throws Exception {
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(key));
return cipher.doFinal(input);
}
/**
* 解密數據
*
* @param input
* @param key
* @return
* @throws Exception
*/
public static byte[] decrypt(byte[] input, byte[] key) throws Exception {
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, getSecretKey(key));
return cipher.doFinal(input);
}
}