iT邦幫忙

2026 iThome 鐵人賽

DAY 14
0
Software Development

我是Java工程師,關於密碼學我想懂的不多系列 第 14 篇

Day13 - 對稱金鑰加密系統 - 操作模式 (一):ECB、CBC 與 Padding 機制

  • 分享至 

  • xImage
  •  

前言:為什麼需要操作模式?

在前一章我們了解到,區塊加密演算法(如 AES、DES)本質上是一個接收固定輸入長度資料的「加密引擎」(例如 AES 只能處理 16 位元組 / 128 位元的區塊)。

然而,我們在真實世界中要加密的資料(如圖片、文章、PDF 檔)長度往往遠大於 16 位元組。如何將任意長度的資料切塊、組合並傳入區塊加密引擎,就是操作模式(Mode of Operation)要解決的核心課題。

今天我們就從最經典、最基礎的兩大模式——ECB 與 CBC,以及處理長度不足的 Padding(填充機制) 開始介紹。

一、 電子密碼本模式:ECB (Electronic Codebook)

ECB 是最直覺、最簡單的操作模式。你可以把它想像成一本「密碼對照本」:資料切成一塊塊,每塊獨立加密,最後直接拼起來。

1. 運算流程

  • 加密公式:

C_i = E_K(P_i)

  • 解密公式:

P_i = D_K(C_i)

明文 P1 ---> [ AES 加密 (Key) ] ---> 密文 C1
明文 P2 ---> [ AES 加密 (Key) ] ---> 密文 C2
明文 P3 ---> [ AES 加密 (Key) ] ---> 密文 C3

操作模式在加密過程中完全不對資料進行任何串接加工,單純將加密後的 16 位元組密文塊 C_i 直接串接輸出。

2. 致命缺點:圖案模式洩漏 (ECB企鵝)

因為每個區塊是完全獨立運算的,只要輸入相同的明文區塊,就會產出完全相同的密文區塊。

這會導致密文保留了明文的「統計結構與規律」。最著名的例子就是將企鵝點陣圖以 ECB 模式加密後,密文依然能清晰看出企鵝的輪廓(著名的 ECB Penguin 漏洞)。因此,在現代密碼學實務中,絕對禁止使用 ECB 模式處理一般資料。

二、 密碼區塊鏈模式:CBC (Cipher Block Chaining)

為了徹底解決 ECB 的圖案規律問題,CBC 模式引進了「鏈接(Chaining)」機制:將前一個區塊的密文,拿來與當前區塊的明文進行 XOR 運算後再送入加密引擎。

1. 關鍵元件:初始向量 (IV, Initialization Vector)

因為第 1 個明文區塊 P_1 前面沒有「前一個區塊的密文」,所以必須由外部傳入一組隨機生成的位元組陣列,稱為 初始向量(IV)。

2. 運算流程

  • 加密公式:
  • 第 1 個區塊:

C_1 = E_K(P_1 ⊕ IV)

  • 第 i 個區塊 (i > 1):

C_i = E_K(P_i ⊕ C_{i-1})

  • 解密公式:
  • 第 1 個區塊:

P_1 = D_K(C_1) ⊕ IV

  • 第 i 個區塊 (i > 1):

P_i = D_K(C_i) ⊕ C_{i-1}

[IV] ---------+
              v
明文 P1 ---> (XOR) ---> [ AES 加密 (Key) ] ---> 密文 C1
                                                  |
              +-----------------------------------+
              v
明文 P2 ---> (XOR) ---> [ AES 加密 (Key) ] ---> 密文 C2

3. 特性與安全性分析

  • 隱蔽圖案規律:即使 P_1 與 P_2 的內容完全相同,因為 P_2 會先與 C_1 進行 XOR,最終產出的密文 C_2 也會截然不同。
  • 解密支援平行運算:加密時因為 C_i 依賴 C_{i-1},所以加密無法平行化;但解密時所有密文塊 C_i 都是現成的,因此解密可以進行平行加速。
  • IV 的安全要求:IV 不需要保密(通常附在密文最前方發送),但必須具備隨機性且不可預測,絕對不能在同一把 Key 下重複使用固定的 IV。

三、 資料填充機制 (Padding)

區塊加密演算法(如 AES)要求每一個輸入區塊的長度必須完全符合規格(AES 為 16 Bytes)。然而,現實中的資料長度幾乎不可能剛好是 16 的倍數。當最後一個區塊的長度不足時,就必須透過 Padding 來補齊。

1. 主流填充標準:PKCS#7 / PKCS#5

最常見的 Padding 方式是 PKCS#7。其規則為:缺了 N 個位元組,就填入 N 個數值為 N 的 Byte。

  • 案例 A(欠缺 3 位元組):
    若最後一塊只有 13 位元組,還差 3 位元組,填充內容為:
    [Data...] + 0x03 0x03 0x03
  • 案例 B(欠缺 1 位元組):
    若最後一塊有 15 位元組,還差 1 位元組,填充內容為:
    [Data...] + 0x01
  • 案例 C(長度剛好整除!):
    若資料剛好是 16 位元組的倍數,依然必須額外補上一整個 16 位元組的 Padding 區塊(全部為 0x10):
    [Data (16 bytes)] + [0x10 0x10 ... 0x10 (16 bytes)]
  • 原因:若不額外補充一整塊,解密端將無法分辨「最後一個 Byte 的 0x01 究竟是 Padding 還是原本的明文資料」。

2.差異比較

比較項目 PKCS#5 Padding PKCS#7 Padding
規範來源 RFC 2898 (PKCS#5 v2.1) RFC 2315 / RFC 5652 (PKCS#7)
適用區塊大小 固定 8 位元組 (64 bits) 1 至 255 位元組
常見搭配演算法 DES、3DES AES (16 位元組) 及其他區塊演算法
填充邏輯 缺 N 個位元組,就補 N 個數值為 N 的 Byte 缺N 個位元組,就補 N 個數值為 N 的 Byte

四、 Java JCA 設定對照表

在 Java JCA 中,我們傳給 Cipher.getInstance() 的字串,格式由 「演算法/操作模式/填充機制」 三者組合而成:


// 經典對稱加密寫法 (CBC 模式 + PKCS#7 填充)
// (註:Java 歷史因素,PKCS5Padding 在 AES 16-byte 下運作等同於 PKCS#7)
Cipher cbcCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

為什麼使用PKCS#5會是PKCS#7

  • 歷史因素:早期 Java JCA 推出時,主要使用的是 8 位元組的 DES/3DES,當時字串便命名為 PKCS5Padding。
  • Java 的自動支援:當你針對 AES(區塊大小 16 位元組)指定 PKCS5Padding 時,Java 底層會自動將其視為針對 16 位元組區塊的 PKCS#7 Padding 運作。

Reference

  • 密碼學導論課程 - 陳君明教授

上一篇
Day12 - 對稱金鑰加密系統:區塊密碼(Block Cipher)
下一篇
Day14 - 對稱金鑰加密系統 - 操作模式 (二):CFB與OFB
系列文
我是Java工程師,關於密碼學我想懂的不多 共 17 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言