AES (Advanced Encryption Standard) 是目前對稱加密的工業標準。Java 提供完善的 JCA/JCE API,調用簡單但需注意模式、填充、金鑰長度等細節。本文提供最基礎的 AES-128 ECB/NoPadding 實作,作為進階模式(CBC、GCM 等)的入門基石。
import javax.crypto.*;
import javax.crypto.spec.*;
import java.security.*;
public class AESCipher {
private final byte[] aesKey = new byte[16]; // AES-128 = 16 bytes
private Cipher cipher;
private SecretKeySpec secretKey;
public AESCipher() {
// 示範用固定金鑰,實務請用 PBKDF2/SCrypt/Argon2 衍生
for (int i = 0; i < 16; i++) aesKey[i] = 0x01;
}
public void init() throws Exception {
secretKey = new SecretKeySpec(aesKey, "AES");
// ECB 模式不需 IV,NoPadding 要求資料為 16 bytes 倍數
cipher = Cipher.getInstance("AES/ECB/NoPadding");
}
public byte[] encrypt(byte[] plaintext) throws Exception {
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
return cipher.doFinal(plaintext);
}
public byte[] decrypt(byte[] ciphertext) throws Exception {
cipher.init(Cipher.DECRYPT_MODE, secretKey);
return cipher.doFinal(ciphertext);
}
}
public static void main(String[] args) {
try {
AESCipher cipher = new AESCipher();
cipher.init();
// 測試資料:16 bytes (1 個區塊)
byte[] input = new byte[16];
for (int i = 0; i < 16; i++) input[i] = 0x01;
System.out.println("原文: " + bytesToHex(input));
byte[] encrypted = cipher.encrypt(input);
System.out.println("密文: " + bytesToHex(encrypted));
byte[] decrypted = cipher.decrypt(encrypted);
System.out.println("解密: " + bytesToHex(decrypted));
} catch (Exception e) {
e.printStackTrace();
}
}
private static String bytesToHex(byte[] data) {
StringBuilder sb = new StringBuilder();
for (byte b : data) sb.append(String.format("%02X", b));
return sb.toString();
}
| 模式 | 需 IV | 平行運算 | 適用場景 | 備註 |
|---|---|---|---|---|
| ECB | 否 | 是 | 極少(僅教學/測試) | 相同明文產生相同密文,嚴重洩漏模式 |
| CBC | 是 | 否(加密)/是(解密) | 通用加密 | 需隨機 IV,配合 PKCS5Padding |
| CTR | 是 | 是 | 串流加密、隨機存取 | 將區塊密碼轉為串流密碼 |
| GCM | 是 | 是 | 推薦:生產環境首選 | AEAD 模式,同時提供機密性+完整性驗證 |
IllegalBlockSizeException// 生產環境推薦:AES-256-GCM (AEAD)
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
SecretKeySpec keySpec = new SecretKeySpec(deriveKey(password, salt), "AES");
byte[] iv = new byte[12]; // GCM 建議 96-bit IV
SecureRandom random = new SecureRandom();
random.nextBytes(iv);
GCMParameterSpec gcmSpec = new GCMParameterSpec(128, iv); // 128-bit 標籤
cipher.init(Cipher.ENCRYPT_MODE, keySpec, gcmSpec);
byte[] ciphertext = cipher.doFinal(plaintext);
// 輸出格式:IV (12 bytes) + ciphertext + authTag (16 bytes)
CipherInputStream/CipherOutputStream 串流處理javax.crypto.Cipher 的多執行緒並行從 ECB/NoPadding 起步,理解區塊、模式、填充、IV、金鑰長度的關係,再進階至 GCM,才能在實務中正確選型並避開常見坑點。