一個區塊密碼(block cipher)由一個加密演算法與一個解密演算法組成:

  • 加密演算法 E 接收金鑰 K 與明文區塊 P,產生密文區塊 C,寫作 C = E(K, P)
  • 解密演算法 D 是加密演算法的反函式,把訊息解回原始明文 P,寫作 P = D(K, C)

由於兩者互為反函式,加密與解密演算法通常涉及相似的操作。

安全目標#

若你跟上了先前關於加密、隨機性與不可區分性的討論,安全區塊密碼的定義就不會讓你意外——我們仍然把安全性定義為「看起來夠隨機」。

一個區塊密碼要安全,它必須是一個偽隨機置換(PRP,pseudorandom permutation):只要金鑰保密,攻擊者就不應該能從任何輸入算出該區塊密碼的輸出。

也就是說,只要 K 從攻擊者的角度是秘密且隨機的,對任何給定的 P,他們都應該對 E(K, P) 長什麼樣毫無頭緒。

更一般地說:

  • 攻擊者不該能在區塊密碼的輸入/輸出值中發現任何樣式。
  • 在對某個固定且未知金鑰之加密與解密函式擁有黑箱存取權的情況下,應該不可能把區塊密碼與真正的隨機置換區分開來
  • 同理,攻擊者不該能還原安全區塊密碼的秘密金鑰——否則他們就能用那把金鑰把區塊密碼與隨機置換區分開來。
  • 這當然也意味著攻擊者無法預測某段由該區塊密碼產出之密文所對應的明文。

區塊大小#

有兩個值刻畫一個區塊密碼:區塊大小金鑰長度。安全性取決於兩者。

多數區塊密碼的區塊是 64 位元或 128 位元——DES 的區塊有 64(2^6)位元,AES 的區塊有 128(2^7)位元。在計算中,2 的冪次長度能簡化資料處理、儲存與定址。

但為什麼是 2^6 與 2^7,而不是 2^4 或 2^16?

區塊不能太大#

  • 密文長度:區塊密碼處理的是區塊而非位元。這意味著若區塊是 128 位元,要加密一則 16 位元的訊息,你得先把它轉換成一個 128 位元區塊,區塊密碼才會處理它並回傳 128 位元的密文。區塊越寬,這個額外開銷就越長。
  • 記憶體足跡:要處理一個 128 位元區塊,你至少需要 128 位元的記憶體。這夠小,能放進多數 CPU 的暫存器,或以專用硬體電路實作。64、128 甚至 512 位元的區塊都短到足以在多數情況下有效率地實作,但更大的區塊(例如好幾 KB 長)會對實作的成本與效能造成顯著衝擊

當密文長度或記憶體足跡至關重要時,你可能得用 64 位元區塊,因為它們產生較短的密文、消耗較少記憶體。

否則 128 位元或更大的區塊更好——主要是因為在現代 CPU 上 128 位元區塊比 64 位元的處理起來更有效率,而且更安全。特別是 CPU 能利用特殊指令平行處理一個或多個 128 位元區塊,例如 Intel CPU 的 AVX(Advanced Vector Extensions)指令家族。

區塊也不能太小#

區塊太小時,它們可能受碼本攻擊(codebook attack)——這是一類只在區塊較小時才有效率的區塊密碼攻擊。

以 16 位元區塊為例,碼本攻擊的流程是:

  1. 取得對應於每個 16 位元明文區塊的 65536(2^16)個密文。
  2. 建立一張查找表(也就是碼本),把每個密文區塊映射到對應的明文區塊。
  3. 要解密一個未知的密文區塊,就在表中查出它對應的明文區塊。

各區塊大小所需的記憶體:

區塊大小查找表大小可行性
16 位元2^16 × 16 = 2^20 位元(128 KB)輕鬆
32 位元16 GB仍可管理
64 位元2^70 位元(128 EB)免談

對更大的區塊而言,碼本攻擊不成問題。