串流密碼(stream ciphers)比起完整的偽隨機數產生器(PRNG),其實更接近確定性隨機位元產生器(DRBG)——因為和 DRBG 一樣,串流密碼是確定性的。
正是這份確定性讓解密成為可能:你可以重新產生當初用來加密的那串偽隨機位元。
若改用 PRNG,你可以加密卻永遠無法解密——安全,但沒用。
與 DRBG 的差別:兩個輸入#
串流密碼與 DRBG 的分別在於:DRBG 只接收單一輸入值,串流密碼則接收兩個值:
- 金鑰(key):應保密,通常 128 或 256 位元。
- nonce:不必保密,但對每把金鑰都必須唯一,通常介於 64 到 128 位元。
nonce 這個名字其實是 number used only once(只用一次的數字)的縮寫。在串流密碼的脈絡下,它有時被稱為 IV(initial value,初始值)。
金鑰流#
串流密碼產生一串偽隨機的位元流,稱為金鑰流(keystream)。金鑰流與明文 XOR 就完成加密,再與密文 XOR 就完成解密:
KS = SC(K, N) 產生金鑰流
C = P ⊕ KS 加密
P = C ⊕ KS 解密其中 SC 是串流密碼演算法、KS 是金鑰流、P 是明文、C 是密文。

圖 5-1:串流密碼如何加密:接收秘密金鑰 K 與公開 nonce N
加密與解密函式完全相同,因為兩者做的是同一件事——把位元與金鑰流 XOR。
這就是為什麼某些密碼學函式庫只提供單一個 encrypt 函式,加密與解密都用它。
絕不重複使用 (K, N)#
串流密碼允許你用金鑰 K₁ 與 nonce N₁ 加密一則訊息,然後:
- 用
K₁與另一個 nonceN₂(≠N₁)加密另一則訊息,或 - 用另一把金鑰
K₂(≠K₁)與 nonceN₁加密。
但你絕不該再次用
K₁與N₁加密,因為那會讓同一串金鑰流KS被用兩次。屆時你會有
C₁ = P₁ ⊕ KS與C₂ = P₂ ⊕ KS;若你知道P₁,就能算出:P₂ = C₁ ⊕ C₂ ⊕ P₁
兩種架構#
從高層次看,串流密碼分成兩類。
有狀態串流密碼#
有狀態串流密碼(stateful stream ciphers)擁有一個在金鑰流產生過程中不斷演化的秘密內部狀態。
密碼先從金鑰與 nonce 初始化狀態,接著呼叫一個 update 函式來更新狀態值,並從狀態產生一個或多個金鑰流位元。

圖 5-2:有狀態串流密碼
著名的 RC4 就是有狀態密碼。
計數器式串流密碼#
計數器式串流密碼(counter-based stream ciphers)從金鑰、nonce 與一個計數器值產生金鑰流片段。
與有狀態串流密碼不同,金鑰流產生過程中不會記憶任何秘密狀態。Salsa20 屬於這一類。

圖 5-3:計數器式串流密碼
兩種內部實作取向#
上述兩種取徑定義的是串流密碼的高層次架構,與核心演算法如何運作無關。
串流密碼的內部結構也分成兩類,取決於密碼的目標平台:硬體導向與軟體導向。