Understand AES best practices, block filling, and Modes

了解 AES 最佳實踐、區塊填充與模式

前言

AES(Advanced Encryption Standard)是最廣泛使用的對稱加密,HTTPS/TLS、Wi-Fi(WPA2/3)、全硬碟加密(BitLocker、FileVault)、ZIP/7z 壓縮加密、訊息應用(Signal、WhatsApp)都依賴它。透過理解 AES 如何運作有助於了解現代安全加密如何實踐。

了解加密與 AES

為什麼用 AES

所謂「對稱加密演算法」意味著對明文資料(PlainText)透過金鑰(Key)進行演算生成密文(Cipher),也能反向操作。考慮到可行性,AES 是目前在「安全性、效能與硬體支援」之間取得最佳平衡的對稱加密標準之一。

完美加密的配方

舉例最簡單經典的加密像是一次性密碼本 (One-Time Pad, OTP),在電腦中任何資料可以視為一連串的 0 與 1,而透過與明文同長度、真隨機、只使用一次的情況下與明文進行 XOR 運算,即使攻擊者擁有無限的計算能力,也無法從密文推導出明文。

要達成完善保密性🔗條件非常嚴苛(如 OTP 幾乎無法實務使用),Claude Shannon 提出的概念讓我們能在「理論安全」與「實務可行」之間取得平衡:

  • 混淆(Confusion):隱藏金鑰與密文之間的關係,使攻擊者難以推導金鑰
  • 擴散(Diffusion):讓明文的每個位元影響到密文的多個位元,避免局部模式被保留

AES 運作原理

AES 是一種區塊加密算法,固定一次處理 128 bit 的資料,而金鑰有 128 / 192 / 256 bit 的大小。

  • 每次處理固定長度資料(128 bits = 16 bytes)
  • 使用同一把 Key 做加密與解密
  • 透過多輪轉換讓資料變得難以還原

AES 會把 16 bytes 的資料視為一個 4x4 矩陣(state):

[ a0 a4 a8 a12 ]
[ a1 a5 a9 a13 ]
[ a2 a6 a10 a14 ]
[ a3 a7 a11 a15 ]
  • SubBytes(位元替換)
  • ShiftRows(列位移)
  • MixColumns(欄混合)
  • AddRoundKey(加上金鑰)

AES 運作模式

AES 本身只負責「加密一個區塊」,但實際資料通常很長,因此需要「運作模式」來處理大量的區塊加密:

ECB(Electronic Codebook,電碼本模式)

每個區塊獨立加密,相同的明文區塊產生相同的密文區塊。這是最大的安全缺陷-加密圖片時能直接看出原圖的輪廓。實際開發不要使用。

CBC(Cipher Block Chaining,密碼塊連結模式)

每塊明文先與上一塊密文做 XOR,然後加密。第一塊用隨機產生的 IV(初始向量)代替。相同的明文 + 不同 IV → 完全不同的密文。缺點是必須串列加密,不能並行,是過去最常見的對稱加密模式之一。

CTR(Counter,計數器模式)

把區塊密碼變成流密碼:加密一個遞增的計數器(Nonce + 計數),產生金鑰流,再與明文 XOR。每塊可以獨立計算,支援完全並行,也不需要填充。注意:同一個 Nonce 絕對不能用兩次。

GCM(Galois/Counter Mode)

在 CTR 基礎上加了 GHASH 認證演算法,可以產生一個 Auth Tag(認證標籤)。解密時驗證 Auth Tag,可以偵測資料是否被竄改。同時提供加密和完整性認證,目前最推薦的模式,HTTPS/TLS 廣泛使用。

CFB / OFB

兩者也是將塊密碼變成流密碼的變種,CFB 依賴前一密文塊(類似CBC),OFB 獨立於密文,比較適合對實時性要求高的場景。

PKCS7 填充

缺幾個 byte,就填幾個值為「缺少數量」的 byte

區塊加密有固定的大小,而 PKCS7 Padding 是一種區塊加密的填充方式,用來讓明文長度對齊區塊大小。支援的區塊大小:1 ~ 255 bytes 皆可,最常見搭配:AES(16 bytes 區塊)

區塊大小 = 8 bytes,明文 = HELLO(5 bytes)
原始: H E L L O
缺少: 3 bytes
填充後:H E L L O 03 03 03
再一個例子,明文 = HELLO123(剛好 8 bytes):
即使剛好對齊,也要加一個完整區塊,否則解密時無法判斷結尾:
H E L L O 1 2 3 | 08 08 08 08 08 08 08 08
缺 1 byte → 填 01
缺 2 bytes → 填 02 02
缺 5 bytes → 填 05 05 05 05 05
缺 16 bytes→ 填 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10

解密後如何去除 Padding?

讀最後一個 byte 的值 → 去掉那麼多個 byte

length := len(plaintext)
unpadding := int(plaintext[length-1])
plaintext = plaintext[:(length - unpadding)]

常見漏洞:Padding Oracle Attack🔗

如果系統在解密失敗時回傳不同的錯誤訊息,攻擊者可以利用這個差異逐步還原明文,這就是 Padding Oracle Attack。

  • 使用 AES-GCM(不需要 padding 的 AEAD 模式)
  • 錯誤訊息不洩漏 padding 是否正確

初始向量 IV

IV / Nonce 需「不可重複(unique)」,某些模式(如 CBC)還要求隨機性

初始向量🔗(Initialization Vector,IV)是在加密過程中引入的一段隨機資料,用來確保相同的明文在每次加密後產生不同的密文。

  1. 模式洩漏:為了避免攻擊者觀察特定密文塊反覆出現進而推斷出對應的原文內容(Fixed IV Penguin)
  2. 重復使用:當相同的 IV 搭配相同的金鑰被重複使用於加密,會造成 Many-Time Pad 問題

通常會以明文形式附加在加密資料的前端,因為解密端需要同一個 IV 才能還原第一塊資料。

總結

正確的演算法 + 正確使用 = 真正安全
  • 使用成熟的實踐(標準函式庫、成熟套件)
  • IV 可以公開但務必隨機(至少密碼學安全的僞隨機數)
  • 金鑰透過環境變數提供
  • 新專案優先用 AES-256-GCM;需要相容舊系統時用 AES-128-CBC + PKCS7;永遠不要用 ECB。

延伸閱讀