AES算法(Advanced Encryption Standard,高级加密标准) 是一种广泛使用的对称密钥加密算法,用于保护电子数据的机密性。它取代了旧的DES(数据加密标准),成为全球政府、金融、互联网等领域事实上的加密标准。
以下是关于AES的核心要点:
1. 核心特性
- 对称加密:加密和解密使用同一个密钥(与RSA的非对称加密不同)。
- 分组密码:将明文数据分成固定长度的块(Block)进行加密(AES块大小为128位)。
- 密钥长度可选:支持128位、192位、256位三种密钥长度(安全性递增)。
- 高效可靠:软硬件实现效率高,抗已知攻击(如差分/线性密码分析)。
2. 算法结构:迭代的“轮函数”
AES通过多轮重复操作(称为轮函数)实现加密。轮数取决于密钥长度:
- 128位密钥:10轮
- 192位密钥:12轮
- 256位密钥:14轮
每轮操作(对数据块的处理):
- SubBytes(字节替换)
- 使用S盒(替换表) 对每个字节非线性替换,增加混淆性。
- ShiftRows(行移位)
- 将数据块视为4×4矩阵,每行循环左移不同偏移量(第0行不移,第1行移1位,以此类推)。
- MixColumns(列混合)
- 对每一列进行线性变换(矩阵乘法),扩散字节间的影响。
- AddRoundKey(轮密钥加)
- 将当前轮密钥(由初始密钥扩展生成)与数据块按位异或(XOR)。
首轮和末轮有细微调整:
- 首轮前仅执行
AddRoundKey(初始轮密钥加)。- 末轮省略
MixColumns步骤。
3. 密钥扩展(Key Expansion)
- 将初始密钥扩展生成多个轮密钥(总轮数+1个)。
- 通过循环移位、S盒替换、与轮常数异或等操作生成新密钥。
4. 解密过程
解密是加密的逆过程,依次执行逆操作:
逆字节替换(InvSubBytes) → 逆行移位(InvShiftRows) → 逆列混合(InvMixColumns) → 轮密钥加(AddRoundKey)。
5. 安全性
- 理论安全:目前无已知实用性的数学攻击能破解AES(128位及以上密钥)。
- 暴力破解不可行:
AES-128:尝试所有密钥需 (2^{128}) 次操作(宇宙寿命内无法完成)。AES-256:被NSA用于保护最高机密信息(TOP SECRET)。
- 侧信道攻击:实际应用中需防范时序攻击、功耗分析等(通过硬件安全设计抵御)。
6. 应用场景
AES无处不在,几乎所有需要加密的场景都有它的身影:
- 网络通信:HTTPS/SSL/TLS、VPN(如IPsec)、Wi-Fi(WPA2/WPA3)。
- 文件/磁盘加密:BitLocker(Windows)、FileVault(macOS)、Veracrypt。
- 数据存储:数据库加密、云存储(AWS S3服务端加密)。
- 加密货币:加密钱包、区块链交易隐私保护。
- 软件保护:授权验证、防篡改。
7. 为什么AES比DES更好?
| 特性 | DES(已淘汰) | AES |
|---|---|---|
| 密钥长度 | 56位(易被暴力破解) | 128/192/256位(抗暴力) |
| 分组大小 | 64位 | 128位(更安全高效) |
| 设计结构 | Feistel网络 | SPN结构(扩散性更强) |
| 效率 | 慢(硬件优化差) | 软硬件均高效 |
8. 重要事实
- 标准化:2001年由NIST(美国国家标准与技术研究院) 正式选定(击败其他候选算法如Twofish、Serpent)。
- 设计者:比利时密码学家Joan Daemen与Vincent Rijmen(原名Rijndael)。
- 开放免费:AES不受专利限制,可自由使用。
总结
AES是当今最安全、最高效的对称加密算法,凭借其严谨的数学结构、灵活的密钥长度和广泛的工业支持,成为保护数字世界的基石技术。无论是个人隐私还是国家安全,AES都在幕后默默提供强大的加密保障。
AES对象:
@Data
public class AESUtil {private final String AES = "AES";private Cipher cipher = Cipher.getInstance(AES);public AESUtil() throws Exception {}/*** 加密** @param content 需要加密的内容* @return*/public byte[] encrypt(String password, String content) {try {
// KeyGenerator keyGen = KeyGenerator.getInstance("AES");
// keyGen.init(256, new SecureRandom(password.getBytes()));
// SecretKeySpec key = new SecretKeySpec(keyGen.generateKey().getEncoded(), "AES");SecretKeySpec key = new SecretKeySpec(password.getBytes(), AES);byte[] byteContent = content.getBytes(StandardCharsets.UTF_8);cipher.init(Cipher.ENCRYPT_MODE, key);return cipher.doFinal(byteContent);} catch (Exception e) {e.printStackTrace();System.out.println("AES加密失败" + e.getMessage());}return null;}/*** 解密** @param content 需要解密的内容* @return*/public byte[] decrypt(String password, byte[] content) {try {
// KeyGenerator keyGen = KeyGenerator.getInstance("AES");
// keyGen.init(256, new SecureRandom(password.getBytes()));
// SecretKeySpec key = new SecretKeySpec(keyGen.generateKey().getEncoded(), "AES");SecretKeySpec key = new SecretKeySpec(password.getBytes(), AES);cipher.init(Cipher.DECRYPT_MODE, key);return cipher.doFinal(content);} catch (Exception e) {e.printStackTrace();System.out.println("AES加密失败" + e.getMessage());}return null;}
}
目标接口:AESTargetAble
public interface AESTargetAble {/*** 加密** @param content 需要加密的内容* @return*/byte[] encrypt(String password, String content);/*** 解密** @param content 需要解密的内容* @return*/byte[] decrypt(String password, byte[] content);/*** 采用AES/ECB/NoPadding时,要求密钥长度16、24、32中的一个、待加密内容的byte[]长度必须是16的倍数** @param content 需要加密的内容* @return*/byte[] encryptOther(String password, String content);/*** 采用AES/ECB/NoPadding时,要求密钥长度16、24、32中的一个、待加密内容的byte[]长度必须是16的倍数** @param content 需要解密的内容* @return*/byte[] decryptOther(String password, byte[] content);}
适配器Wrapper
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Wrapper implements AESTargetAble {private AESUtil aesUtil;/*** 加密** @param password* @param content 需要加密的内容* @return*/@Overridepublic byte[] encrypt(String password, String content) {return aesUtil.encrypt(password, content);}/*** 解密** @param password* @param content 需要解密的内容* @return*/@Overridepublic byte[] decrypt(String password, byte[] content) {return aesUtil.decrypt(password, content);}/*** 采用AES/ECB/NoPadding时,要求密钥长度16、24、32中的一个、待加密内容的byte[]长度必须是16的倍数** @param password* @param content 需要加密的内容* @return*/@Overridepublic byte[] encryptOther(String password, String content) {try {SecretKeySpec keySpec = new SecretKeySpec(password.getBytes(), aesUtil.getAES());aesUtil.setCipher(Cipher.getInstance("AES/ECB/NoPadding"));byte[] contentBytes = content.getBytes(StandardCharsets.UTF_8);Cipher cipher = aesUtil.getCipher();cipher.init(Cipher.ENCRYPT_MODE, keySpec);return cipher.doFinal(password.getBytes());} catch (Exception e) {e.printStackTrace();System.out.println("AES加密失败" + e.getMessage());}return null;}/*** 采用AES/ECB/NoPadding时,要求密钥长度16、24、32中的一个、待加密内容的byte[]长度必须是16的倍数** @param password* @param content 需要解密的内容* @return*/@Overridepublic byte[] decryptOther(String password, byte[] content) {try {byte[] bytePassword = password.getBytes();
// bytePassword = checkByteLength(bytePassword);SecretKeySpec keySpec = new SecretKeySpec(bytePassword, "AES");Cipher cipher = aesUtil.getCipher();cipher.init(Cipher.DECRYPT_MODE, keySpec);return cipher.doFinal(content);} catch (Exception e) {e.printStackTrace();System.out.println("AES解密失败" + e.getMessage());}return null;}
}
测试类:
public class AESMain {public static void main(String[] args) throws Exception {String password = "passwordpassword";String content = "学习算法,有益身心健康!!";AESUtil aesUtil = new AESUtil();Wrapper wrapper = new Wrapper(aesUtil);byte[] encryptResult = wrapper.encrypt(password, content);byte[] decryptResult = wrapper.decrypt(password, encryptResult);System.out.println("加密后的数据:" + Base64.getEncoder().encodeToString(encryptResult));System.out.println("解密后的数据:" + new String(decryptResult));//采用AES/ECB/NoPadding时,要求密钥长度16、24、32中的一个、待加密内容的byte[]长度必须是16的倍数byte[] encryptOther = wrapper.encryptOther(password, content);byte[] decryptOther = wrapper.decryptOther(password, encryptOther);System.out.println("加密后的数据:" + Base64.getEncoder().encodeToString(encryptOther));System.out.println("解密后的数据:" + new String(decryptOther));}
}
