首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java AES 加密算法實戰詳解:ECB/CBC 模式、填充模式、IV 向量完整指南

     編輯:Java 相關知識

AES 算法基礎知識

AES (Advanced Encryption Standard),高級加密標準,是對稱分組加密算法標準。核心特性:

  • 分組長度:固定 128 位 (16 字節)
  • 密鑰長度:128/192/256 位(Java 默認 128 位,需 JCE 無限制策略支持 256 位)
  • 工作模式:ECB、CBC、CTR、GCM 等
  • 填充模式:PKCS5Padding、PKCS7Padding、NoPadding 等

Java 加密架構 (JCA) 核心類

類/接口作用
Cipher加密/解密核心引擎,無狀態,需 init 初始化
KeyGenerator對稱密鑰生成器
SecretKey對稱密鑰接口
IvParameterSpec初始化向量 (IV) 參數規範
SecretKeySpec從字節數組構建密鑰

四種常見模式組合實戰

模式 1:AES/ECB/PKCS5Padding(最簡單,不推薦生產)

public static void ecbPkcs5(String plaintext) throws Exception {
    Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
    SecretKey key = KeyGenerator.getInstance("AES").generateKey(); // 隨機密鑰
    
    cipher.init(Cipher.ENCRYPT_MODE, key);
    byte[] encrypted = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));
    System.out.println("加密: " + Base64.getEncoder().encodeToString(encrypted));
    
    cipher.init(Cipher.DECRYPT_MODE, key);
    byte[] decrypted = cipher.doFinal(encrypted);
    System.out.println("解密: " + new String(decrypted, StandardCharsets.UTF_8));
}

缺點:相同明文產生相同密文,模式可見性差,不安全。

模式 2:AES/CBC/PKCS5Padding(生產標準推薦)

public static void cbcPkcs5(String plaintext) throws Exception {
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    SecretKey key = KeyGenerator.getInstance("AES").generateKey();
    byte[] iv = generateSecureIV(); // 16 字節安全隨機 IV
    
    cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
    byte[] encrypted = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));
    System.out.println("IV: " + Base64.getEncoder().encodeToString(iv));
    System.out.println("加密: " + Base64.getEncoder().encodeToString(encrypted));
    
    cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
    byte[] decrypted = cipher.doFinal(encrypted);
    System.out.println("解密: " + new String(decrypted, StandardCharsets.UTF_8));
}

private static byte[] generateSecureIV() {
    byte[] iv = new byte[16];
    new SecureRandom().nextBytes(iv);
    return iv;
}

關鍵點:

  • IV 必須 16 字節,每次加密生成新的隨機 IV
  • IV 無需保密,但必須不可預測,通常與密文一起存储/傳輸
  • PKCS5Padding 自動處理非 16 倍數長度數據

模式 3:AES/CBC/NoPadding(手動填充,特殊場景)

public static void cbcNoPadding(String plaintext) throws Exception {
    // 前提:明文長度必須是 16 字節倍數
    if (plaintext.getBytes(StandardCharsets.UTF_8).length % 16 != 0) {
        throw new IllegalArgumentException("NoPadding 要求數據長度為 16 倍數");
    }
    
    Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
    SecretKey key = KeyGenerator.getInstance("AES").generateKey();
    byte[] iv = "1234567812345678".getBytes(StandardCharsets.UTF_8); // 固定 IV 僅演示
    
    cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
    byte[] encrypted = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));
    
    cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
    byte[] decrypted = cipher.doFinal(encrypted);
    System.out.println("解密: " + new String(decrypted, StandardCharsets.UTF_8));
}

模式 4:指定密鑰加密(實際業務場景)

public static void encryptWithFixedKey(String plaintext, String base64Key, String base64Iv) throws Exception {
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    
    // 從 Base64 還原密鑰和 IV
    byte[] keyBytes = Base64.getDecoder().decode(base64Key);
    byte[] ivBytes = Base64.getDecoder().decode(base64Iv);
    
    SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
    IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);
    
    cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
    byte[] encrypted = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));
    return Base64.getEncoder().encodeToString(encrypted);
}

填充模式對比與選擇

填充模式填充規則適用場景數據長度要求
PKCS5Padding缺幾字節填幾個該數值字節通用推薦,Java 默認任意長度
PKCS7Padding同 PKCS5,支持更大分組BouncyCastle 提供任意長度
NoPadding不填充數據已對齊、流式加密、自定義填充必須是 16 倍數
ISO10126Padding隨機填充,最後字節標示長度舊系統兼容任意長度

密鑰管理最佳實踐

  1. 密鑰生成:使用 KeyGenerator 或 PBKDF2 從密碼派生(SecretKeyFactory)
  2. 密鑰存儲:密鑰管理系統 (KMS)、硬件安全模塊 (HSM)、環境變量(非代碼硬編碼)
  3. 密鑰輪換:定期更換,舊密鑰保留解密歷史數據
  4. IV 生成:SecureRandom 生成 16 字節,每次加密唯一
  5. 認證加密:優先使用 AES-GCM (Java 8+) 同時保證機密性和完整性

AES-GCM 認證加密(現代推薦)

public static String encryptGCM(String plaintext, SecretKey key) throws Exception {
    Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
    byte[] iv = new byte[12]; // GCM 推薦 96 位 IV
    new SecureRandom().nextBytes(iv);
    
    GCMParameterSpec spec = new GCMParameterSpec(128, iv); // 128 位認證標籤
    cipher.init(Cipher.ENCRYPT_MODE, key, spec);
    
    byte[] encrypted = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));
    // 組合:IV + 密文(含認證標籤)
    byte[] combined = new byte[iv.length + encrypted.length];
    System.arraycopy(iv, 0, combined, 0, iv.length);
    System.arraycopy(encrypted, 0, combined, iv.length, encrypted.length);
    return Base64.getEncoder().encodeToString(combined);
}

常見異常與排查

異常原因解決
IllegalBlockSizeExceptionNoPadding 模式下數據非 16 倍數使用 PKCS5Padding 或手動填充
InvalidKeyException: Illegal key size密鑰長度超過默認限制 (128 位)安裝 JCE Unlimited Strength Jurisdiction Policy
InvalidAlgorithmParameterException: Wrong IV lengthIV 長度不等於 16 (CBC) 或 12 (GCM)嚴格按模式要求生成 IV
BadPaddingException解密密鑰/IV 錯誤、數據損壞核對密鑰、IV、確保數據完整傳輸

總結

Java AES 加密核心在於:選對模式(生產首選 CBC+PKCS5Padding 或 GCM)、管好密鑰(隨機生成、安全存儲、定期輪換)、用好 IV(CBC 每次隨機 16 字節、GCM 12 字節)、編碼規範(Base64 存储/傳輸二進制數據)。避免使用 ECB 模式、硬編碼密鑰/IV、自定義填充邏輯。現代應用強烈建議升級到 AES-GCM 獲得認證加密保護。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved