對(duì)稱加密技術(shù) - AES加密
AES的產(chǎn)生目標(biāo)是替代DES(包括3DES)的馆铁,一般情況先推薦優(yōu)先使用AES算法加加密;
AES發(fā)展歷史
- 1997年NIST發(fā)起了整機(jī)替代DES算法的活動(dòng):高級(jí)數(shù)據(jù)加密標(biāo)準(zhǔn)(Advanced Encryption Standard);
- NIST要求算法比3DES快槽惫、安全性缆瓣、具有128位分組長(zhǎng)度匪补、支持128/192/256位長(zhǎng)度的密鑰溃卡;
- 2000年Rijndael算法當(dāng)選AES算法標(biāo)準(zhǔn);
- AES:密鑰建立時(shí)間短币绩、靈敏性好颂碧、內(nèi)存需求低,被廣泛應(yīng)用类浪;
- AES根據(jù)密鑰長(zhǎng)度分為AES-128载城、AES-256幾種。
應(yīng)用
AES
是用來(lái)替代DES的费就,所以凡是可以使用DES
的地方都應(yīng)該優(yōu)先考慮使用AES
替換诉瓦,DES
作為遺留系統(tǒng)或者學(xué)習(xí)保留,實(shí)際建議使用AES
力细,一般場(chǎng)景AES-128
即可睬澡,高安全場(chǎng)景可以使用AES-256
.
在JDK中若要使用256的加密方式需要:無(wú)政策性限制權(quán)限文件。
Java中使用步驟
AES
的使用和DES
一樣眠蚂,也是經(jīng)過(guò)三步煞聪,Java的API封裝的很好,使用SPI機(jī)制實(shí)現(xiàn)策略模式逝慧,外部代碼改動(dòng)很小昔脯。
在使用其他對(duì)稱加密算法:RC2啄糙、RC4急侥、Blowfish算法的時(shí)候都可以參照下面的模式页慷。
- 構(gòu)建密鑰:使用
KeyGenerator
排监,這個(gè)步驟對(duì)稱加密算法和非對(duì)稱加密算法都需要董习; - 構(gòu)建
AES
專用的SecretKey
:和DES
和3DES
不同,使用SecretKeySpec
即可退子,這步是針對(duì)存儲(chǔ)下來(lái)的密鑰進(jìn)行處理窒所; - 進(jìn)行加解密:要注意設(shè)置
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 {
// 產(chǎn)生Key,一般只產(chǎn)生一次鲸拥,Base64工具采用的是JDK 8自帶的工具
byte[] key = generateKey();
String keyStr = Base64.getEncoder().encodeToString(key);
String input = "加密我";
// 加密數(shù)據(jù)
byte[] encryptData = encrypt(input.getBytes(), key);
// 解密數(shù)據(jù)
byte[] dencryData = decrypt(encryptData, key);
String msg = String.format("原始數(shù)據(jù): %s , Key : %s , 加密數(shù)據(jù): %s , 解密數(shù)據(jù): %s", input, keyStr,
HexBin.encode(encryptData), new String(dencryData));
System.out.println(msg);
}
/**
* 產(chǎn)生符合要求的Key,如果不用KeyGenerator隨機(jī)性不好,而且要求自己對(duì)算法比較熟悉,能產(chǎn)生符合要求的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簡(jiǎn)單
*
* @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;
}
/**
* 加密數(shù)據(jù)
*
* @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);
}
/**
* 解密數(shù)據(jù)
*
* @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);
}
}