AES算法模拟对象适配器模式

AES算法(Advanced Encryption Standard,高级加密标准) 是一种广泛使用的对称密钥加密算法,用于保护电子数据的机密性。它取代了旧的DES(数据加密标准),成为全球政府、金融、互联网等领域事实上的加密标准。

以下是关于AES的核心要点:


1. 核心特性

  • 对称加密:加密和解密使用同一个密钥(与RSA的非对称加密不同)。
  • 分组密码:将明文数据分成固定长度的块(Block)进行加密(AES块大小为128位)。
  • 密钥长度可选:支持128位、192位、256位三种密钥长度(安全性递增)。
  • 高效可靠:软硬件实现效率高,抗已知攻击(如差分/线性密码分析)。

2. 算法结构:迭代的“轮函数”

AES通过多轮重复操作(称为轮函数)实现加密。轮数取决于密钥长度:

  • 128位密钥:10轮
  • 192位密钥:12轮
  • 256位密钥:14轮
每轮操作(对数据块的处理)
  1. SubBytes(字节替换)
    • 使用S盒(替换表) 对每个字节非线性替换,增加混淆性。
  2. ShiftRows(行移位)
    • 将数据块视为4×4矩阵,每行循环左移不同偏移量(第0行不移,第1行移1位,以此类推)。
  3. MixColumns(列混合)
    • 对每一列进行线性变换(矩阵乘法),扩散字节间的影响。
  4. 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
     */
    @Override
    public byte[] encrypt(String password, String content) {
        return aesUtil.encrypt(password, content);
    }


    /**
     * 解密
     *
     * @param password
     * @param content  需要解密的内容
     * @return
     */
    @Override
    public byte[] decrypt(String password, byte[] content) {
        return aesUtil.decrypt(password, content);
    }


    /**
     * 采用AES/ECB/NoPadding时,要求密钥长度16、24、32中的一个、待加密内容的byte[]长度必须是16的倍数
     *
     * @param password
     * @param content  需要加密的内容
     * @return
     */
    @Override
    public 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
     */
    @Override
    public 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));
        
    }
}

你可能感兴趣的:(算法,适配器模式,java)