區塊密碼有數百種,但建構它們的技巧只有寥寥幾種。兩個要點:

  • 實務上使用的區塊密碼不是一個巨大的演算法,而是(rounds)的重複——輪是一段短短的運算序列,單獨看很弱,但數量一多就強。
  • 建構「輪」主要有兩種技巧:替換—置換網路(AES 採用)與 Feistel 架構(DES 採用)。

區塊密碼的輪#

計算一個區塊密碼,歸根究柢就是計算一連串的輪。在區塊密碼中,一輪是一個易於規範、易於實作的基本變換,經過數次迭代就形成該區塊密碼的演算法。

這種「小元件重複多次」的建構方式,比起「單一巨大演算法」的建構方式,更容易實作、也更容易分析

例如一個三輪的區塊密碼,把明文加密成 C = R₃(R₂(R₁(P)))。每一輪也必須有反函式,接收者才能算回明文:P = iR₁(iR₂(iR₃(C))),其中 iR₁R₁ 的反函式。

輪金鑰#

輪函式 R₁R₂ 等通常是相同的演算法,但由一個稱為輪金鑰(round key)的值加以參數化。兩個使用相異輪金鑰的輪函式行為會不同,因此餵入相同輸入時會產生相異的輸出。

輪金鑰是用一個稱為金鑰排程(key schedule)的演算法從主金鑰 K 衍生而來:R₁ 用輪金鑰 K₁R₂K₂,依此類推。

每一輪的輪金鑰都應該彼此相異,而且不是所有輪金鑰都該等於金鑰 K

否則所有的輪都會相同,區塊密碼就會變得比較不安全——原因見下。

滑動攻擊#

在區塊密碼中,任何一輪都不該與另一輪相同,以避免滑動攻擊(slide attack)。

滑動攻擊尋找兩組明文/密文對 (P₁, C₁)(P₂, C₂),其中 P₂ = R(P₁)R 是該密碼的輪)。

當各輪相同時,兩段明文之間的關係 P₂ = R(P₁)蘊含其對應密文之間的關係 C₂ = R(C₁)

而且無論有幾輪——3 輪、10 輪還是 100 輪——C₂ = R(C₁) 這個關係都成立。

問題在於:知道單獨一輪的輸入與輸出,往往就足以還原金鑰。

使用不同的輪金鑰作為參數,確保了各輪行為相異,從而挫敗滑動攻擊。

圖 4-1:滑動攻擊的原理:針對各輪相同的區塊密碼

使用輪金鑰的一個潛在副產品與好處,是對旁道攻擊的防護。

若從主金鑰 K 到輪金鑰 Kᵢ 的變換是不可逆的,那麼即使攻擊者找到了 Kᵢ,也無法用它反推 K

遺憾的是,很少區塊密碼具有單向的金鑰排程。例如 AES 的金鑰排程就允許攻擊者從任何一個輪金鑰 Kᵢ 算出 K

詳見 Biryukov 與 Wagner 1999 年的論文〈Advanced Slide Attacks〉。

替換—置換網路(SPN)#

如果你讀過密碼學教科書,一定看過混淆(confusion)與擴散(diffusion)這兩個詞:

  • 混淆:輸入(明文與加密金鑰)經歷複雜的變換。
  • 擴散:這些變換平均地依賴於輸入的所有位元。

概略地說:混淆關乎深度,擴散關乎廣度。

在區塊密碼的設計中,混淆與擴散以替換置換操作的形式出現,兩者結合於替換—置換網路(SPN,substitution–permutation networks)之中。

替換:S-box#

替換常以 S-box(substitution box,替換盒)的形式出現,那是轉換 4 或 8 位元資料塊的小型查找表。

例如區塊密碼 Serpent 的八個 S-box 中的第一個,由 16 個元素組成:

3 8 f 1 a 6 5 b e d 4 2 7 0 9 c

每個元素代表一個 4 位元的 nibble。這個 S-box 把 4 位元 nibble 0000 映射到 30011),把 0101(十進位 5)映射到 60110),依此類推。

S-box 必須被審慎挑選以確保密碼學強度:

  • 盡可能非線性(輸入與輸出之間以複雜的方程式關聯)。
  • 無統計偏差(例如翻轉一個輸入位元,應該有可能影響到任何一個輸出位元)。

置換#

替換—置換網路中的置換,可以簡單到只是改變位元的順序——容易實作,但把位元混合得不夠徹底。

有些密碼不用位元重排,而是用基本線性代數與矩陣乘法來混合位元:它們對固定值(矩陣的係數)執行一連串乘法運算,再把結果相加。這類線性代數運算能快速在密碼內的所有位元之間建立依賴關係,從而確保強擴散。

例如區塊密碼 FOX 把一個 4 位元組向量 (a, b, c, d) 變換成 (a′, b′, c′, d′)

a′ = a + b + c + (2 × d)
b′ = a + (253 × b) + (2 × c) + d
c′ = (253 × a) + (2 × b) + c + d
d′ = (2 × a) + b + (253 × c) + d

上式中的 2 與 253 被解讀為二元多項式而非整數,因此加法與乘法的定義與我們習慣的略有不同——例如不是 2 + 2 = 4,而是 2 + 2 = 0

無論如何,重點是:初始狀態的每個位元組都影響最終狀態的全部 4 個位元組。

Feistel 架構#

1970 年代,IBM 工程師 Horst Feistel 設計了一個名為 Lucifer 的區塊密碼,運作如下:

  1. 把 64 位元區塊拆成兩個 32 位元的半邊 LR
  2. L = L ⊕ F(R),其中 F 是一個替換—置換輪。
  3. 交換 LR 的值。
  4. 回到步驟 2,重複 15 次。
  5. LR 合併成 64 位元的輸出區塊。

這個建構後來被稱為 Feistel 架構(Feistel scheme)。

圖 4-2:Feistel 架構的兩種等價表示法

有一個功能上等價的表示法:不交換 LR,而是讓各輪交替執行 L = L ⊕ F(R)R = R ⊕ F(L)

各輪的 F 函式接收不同的輪金鑰:第一個 FK₁,第二個用 K₂。在 DES 中,F 函式接收一把從 56 位元金鑰 K 衍生出的 48 位元輪金鑰。

PRP 或 PRF 都可以#

在 Feistel 架構中,F 函式可以是偽隨機置換(PRP)或偽隨機函式(PRF):

  • PRP 對任意兩個相異輸入都產出相異輸出。
  • PRF 則存在 XY 使得 F(X) = F(Y)

但在 Feistel 架構中,只要 F 在密碼學上夠強,這個差別無關緊要

該有幾輪#

DES 執行 16 輪,GOST 28147-89 執行 32 輪。

F 函式強到極致,理論上四輪就足夠;但真實的密碼會用更多輪,以防禦 F 中潛在的弱點。