密碼學極速入門,Part-1

科普 | 密碼學極速入門,Part-1


-廣受歡迎的加密通訊工具——OpenSSL,其中的部分代碼-

關於密碼學的內在原理,一直被認為是少數專家或數學家才能涉足的領域,其中的技術細節在大多數人看來就像變魔術一樣。考慮到現代密碼學的複雜程度,我們可以理解為什麼很多人對密碼學存在這些誤解;但不瞭解密碼學,可能會做出很多弊大於利的決定,比如英國的加密禁令提案(Encryption Ban),澳大利亞的援助和訪問法案(Assistance and Access Bill)等。

在本篇指南中,我們會幫助大家掌握學習密碼學所需的入門知識、對不同密碼學體系的發展歷程進行簡介,並對當前三個最流行的密碼學領域——流密碼、分組密碼、公鑰密碼,進行快速上手指導。

密碼(Ciphers)

“密碼”(Cipher)指的是對消息進行加密或解密的算法,也是密碼學的基石。加密算法 (E) 使用密鑰 (k) 對消息 (m) 進行加密,並生成密文 (c);類似地,解密算法 (D) 使用密鑰 (k) ,對密文 (c) 進行解密。如下列所示:

科普 | 密碼學極速入門,Part-1

-加密算法 'E' 及解密算法 'D' -

上述過程也意味著,一種算法要想被稱為“密碼”(算法),還必須滿足以下的一致性方程特性,確保密文可以被解密。

科普 | 密碼學極速入門,Part-1

式子表明著如果你使用密鑰 K 對消息進行加密,也能使用密鑰 K 對密文進行解密,並得到與原來消息一摸一樣的輸出。

其中一種最古老、最簡單的密碼就是凱撒密碼(Caesar Cipher)——直接從字母表中選取特定位置,替換掉原消息中的字符。

科普 | 密碼學極速入門,Part-1

-凱撒密碼出現於公元 50 年,凱撒大帝使用字母表跳三位的字來替換原來的消息內容,用於軍事通訊-

下面的例子就是經過後三位字符替換過後的密文形式(上面一行為原文,下面一行為密文):

科普 | 密碼學極速入門,Part-1

凱撒密碼可以用下列式子表示:

科普 | 密碼學極速入門,Part-1

雖然這種做法符合我們對密碼的定義,但是它非常不安全。只要攻擊者知道密文是以這種方式加密,就能通過嘗試另外 25 種組合進行破譯;即使攻擊者不知道密文使用了凱撒密碼,他們也能夠觀察到密文中的規律進行破譯。

雖然這種做法符合我們對密碼的定義,但是它非常不安全。只要攻擊者知道密文是以這種方式加密,就能通過嘗試另外 25 種組合進行破譯;即使攻擊者不知道密文使用了凱撒密碼,他們也能夠觀察到密文中的規律進行破譯。

在進一步介紹更安全的加密算法之前,我們得先聊聊什麼是 Xor 運算。

XOR(異或運算)

Xor 運算 ,又稱為 “異或門”,是一種布爾變量邏輯判斷,能接收 1 或 0 作為輸入:如果輸出 1 則表示兩個輸入不同;輸出 0 則表示兩個輸入相同。 下圖的真值表列出了經過異或運算後,所有可能的輸入輸出組合:

科普 | 密碼學極速入門,Part-1

異或運算也經常用符號 ⊕ 來表示:

0 ⊕ 0 = 0

0 ⊕ 1 = 1

1 ⊕ 0 = 1

1 ⊕ 1 = 0

關於異或邏輯,以下有幾點重要的特性:

  1. 異或運算結合律:a ⊕ (b ⊕ c) = (a ⊕ b) ⊕ c
  2. 對自身進行異或運算結果為 0 : a ⊕ a = 0
  3. 對 0 求異或,結果為自身:a ⊕ 0 = a

根據上述異或運算的規則,我們知道 a ⊕ b ⊕ a 等同於 a ⊕ a ⊕ b,也等於 0 ⊕ b,運算結果為 b。要注意的是,這些異或運算特性只適用在 1 和 0 ,因此對不同 進制 的數字進行異或運算之前,需要先將其轉換為二進制。例如:

87 ⊕ 73 = 1010111b ⊕ 1001001b = 0011110b = 30

接著,我們可以開始介紹第一種安全密碼了。

一次性密碼

Frank Miller 在1882 年提出了一次性密碼(One-time pad)的概念——加密:將消息和私鑰進行異或運算得到密文;解密:將密鑰和密文進行異或運算得到原消息,這個過程類似於前面提到的 a ⊕ b ⊕ a = b 。一次性密碼的定義如下所示:

科普 | 密碼學極速入門,Part-1

該密碼的一致性方程也很容易證明:

科普 | 密碼學極速入門,Part-1

一次性密碼非常容易上手,假設我們要加密一串字段“Message”,首先可以通過 ASCII 字符集 將“Message”轉換為二進制數據(由 1 和 0 組成)。

科普 | 密碼學極速入門,Part-1

現在,我們需要一組 56 位隨機二進制數(私鑰)來對明文進行異或運算,該私鑰隨機程度越高越好!

科普 | 密碼學極速入門,Part-1

-從 random.org 生成的隨機數-

我們將明文和私鑰的每一位進行異或運算。

科普 | 密碼學極速入門,Part-1

運算後的結果就是我們的密文了!要解開密文也很簡單,我們只需要將密文和剛才生成的私鑰進行異或運算,並轉碼回 ASCII ,就能得到原消息。

科普 | 密碼學極速入門,Part-1


這種密碼簡單易用,而且還有個很有意思的特點。一次性密碼具有所謂的完全保密性,這意味著從數學角度來說,攻擊者不可能從密文(m⊕k 的結果)推得任何原消息的內容,當然也不可能破譯。

既然我們已經有了簡單易用,且不可能破譯的密碼,為什麼我們還會想用其他的密碼呢?根本原因在於,一次性密碼雖然很有效,但是他有一些重大的缺陷。

第一個缺陷是,不論我們想要加密什麼樣的消息,都需要有和原消息一樣長或是更長的私鑰用於加解密。而且為了讓密文接收者能夠解密密文,需要有絕對安全的通信方法把私鑰給到接收者;這就形成一個悖論,如果有這種安全通道,那不如直接把原消息發過去得了。

第二個缺陷可以從 “一次性密碼” 的名稱中發現。針對不同消息,同一個私鑰每回只能使用一次;如果對多個消息重複使用同一個私鑰,其引發的問題可以從數學推導上看出。

假設我們有兩條消息 m1 和 m2 ,分別使用相同的私鑰 k 進行加密(使得我們的系統變成 “二次性密碼”)。通過異或運算,我們會得到以下密文:

科普 | 密碼學極速入門,Part-1

從上圖,我們可以從密文 C1⊕ C2 得到 m1⊕ m2 。對於攻擊者來說,他們就能基於這種關聯性,通過各種統計分析、頻率分析、模式匹配,或是使用 2006 年提出的自然語言處理方法 ,來獲得原消息的內容。我不會深入解釋存在這種關聯性具體造成的危害(感興趣的可以看 這裡 深入瞭解),這裡只是形象的說明當同一個私鑰被使用的次數越多(“三次”、“四次”……?),密碼的安全性就越低。

現在我們已經具備 XOR 加密和一次性密碼的基礎知識,是時候瞭解其他更實用的加密方法了。

流密碼(Stream Ciphers)

一次性密碼具有非常好的安全性,這意味著手上只有密文的情況下,攻擊者不可能進行破譯。但是好的安全性基於長度大於等於原消息的私鑰,這使得一次性密碼並不實用,因為如果加解密雙方有很好的方法來傳遞消息和私鑰,他們直接傳遞消息就好,沒必要進行加密。

為了讓一次性密碼更加實用,我們引入 “流密碼” 的概念。流密碼的核心思想是——以“偽隨機”密鑰替代一次性密碼中的 “隨機” 密鑰,偽隨機密鑰產生自 密碼學安全 偽隨機數生成器( CSPRNG ,Cryptographically Secure Pseudo-random number generator )。要注意的是,CSPRNG 不同於一般的偽隨機數生成器,因為 CSPRNG 產生的數據必須和真實隨機數看起來沒有區別才行。

CSPRNG 是一種算法(或函數),能產生一長串數字,類似於隨機數的性質。因為隨機數很難生成,所以 CSPRNG 要依靠種子(seed)來決定初始狀態及將來產生的數;CSPRNG 從相對較小的起始種子生成海量的隨機數(例如從 128 bit 的種子生成幾 GB 的隨機數)。如果起始種子是已知的,則隨後產生的所有數都是已知的,也就是說 CSPRNG 具有確定性;這也導致CSPRNG 產生的數,其隨機程度完全取決於種子的隨機程度。

為了讓一次性密碼更加實用,我們可以根據所需長度,使用偽隨機數生成器的輸出替換原來的私鑰;這樣的話只要傳遞初始種子就可以了。因為 CPRNG 具有確定性,使用相同種子能得到相同輸出(也就能得到相同的 key 用來加解密)。

為了更好理解,我們先看看原來的一次性密碼:

科普 | 密碼學極速入門,Part-1

使用偽隨機數生成器的輸出 G(K),替換原來的私鑰 K:

使用偽隨機數生成器的輸出 G(K),替換原來的私鑰 K:

科普 | 密碼學極速入門,Part-1

(注:圖例中只是其中一種流密碼,稱為同步流密碼。還有一種方法稱為 “ 自同步流密碼 ”,使用密文中的前幾位數計算出密鑰中的每一位。)

替換後的私鑰可以遠遠短於要加密的消息,使得分配及管理私鑰更為方便,進一步改善了一次性密碼不實用的問題。但這種做法也帶來了新的問題:

將原來完全隨機的私鑰替換為安全隨機數生成器的輸出,會導致私鑰長度比原消息短,使得我們的密碼不再具有完全保密性。因此流密碼的安全性取決於我們的偽隨機數生成器的不可預測性。如果可以預測 CSPRNG 的輸出,則可以獲得明文消息。以下是大家熟知的一些使用弱流密碼的密碼系統:

802.11b WEP:WEP 是一種給 WiFi 數據做加密的算法,它使用的流密碼稱為 RC4 。因為流密碼中不能一直使用同個密鑰,所以長期使用的密鑰包含一個每次都會變動的值 “IV”;然而 “IV”只有 24 位,也就是說加密超過 5000 條消息後,就會有五成的概率出現相同的密鑰。

CSS:DVD Forum 使用內容擾亂系統(CSS, Content Scramble System)來管理 DVD 的數字版權,使得僅有獲得授權的應用才能訪問 DVD 內容。CSS 使用 40 位的密鑰,而 40 位的密鑰空間較小,可以相對快速地暴力破解。(儘管密鑰是 40 位,但考慮到 CSPRNG 的技術特點,只要猜出 17 位組合後,系統便可能被完全破解。)

現在我們也掌握了流密碼的知識,可以進一步討論下一個密碼系統——分組密碼。

分組密碼(Block Ciphers)

分組密碼是另一種能用於加解密數據的方法。分組密碼包含兩種算法:E 用於加密,D 用於解密,同時也用到了密鑰 K 。

科普 | 密碼學極速入門,Part-1

分組密碼的核心在於,要加密的明文和輸出的密文長度始終相同,為一固定量。該固定量稱為 “block size”(譯者注:不要與區塊鏈語境下的 “block size” 搞混哦;後文將該詞譯為 “消息大小”),大小取決於所使用的分組密碼算法。另外,私鑰 K 的長度被稱為密鑰大小,也是固定量。常見的兩種分組密碼分別是 3DES 及 AES —— 3DES 具有 64 位的消息大小和 168 位的密鑰; AES 具有 128 位的消息大小和 128 、192 或 256 位的密鑰。

因為分組密碼把可能的區塊映射到其他的每一個區塊,所以也被稱為 “用密鑰完成的置換”(Keyed Permutations) 或是 “偽隨機置換”(Pesudorandom Permutations)。非常重要的一點是,私鑰決定了輸入的區塊和相關密文區塊的映射關係,而且是一對一排列的,所以只要知道私鑰就能解密密文。

第一個比較重要的分組密碼是 1970 年代 IBM 開發的數據加密標準( DES ),但 DES 並不安全,很快就被 3DES 取代;緊接著 3DES 又被 1997 年開發的高級加密標準( AES )所取代。AES 是在國家標準與技術研究所( National Institute of Standards and Technology )的要求下制定的標準化分組密碼。 AES 是當今使用的最常見的分組密碼,重要性大大超過 DES 和 3DES ,所以我將著重介紹 AES 。

在我解釋 AES 到底是怎麼運作之前,先提醒一下我會跳過很多技術細節,如果有人對這深入這方面領域有興趣,可以從 這裡 獲得你想要的。

AES 及大部分分組密碼,都是通過迭代進行運作的,輸入的文本消息會使用連續的密鑰以迭代的方式進行加密。第一步是獲得一個密鑰 K,密鑰一般是 128 位、192 位或 256 位的,在這裡我們只演示 128 位的 AES;然後拿該密鑰推導出一系列的 Round Keys 來加密我們的消息。

科普 | 密碼學極速入門,Part-1

上圖例子中,我們輸入 128 位(16 字節)的密鑰,並通過 Rijndael 密鑰方法 將密鑰擴展成 11 個 16 字節的子密鑰。接著,AES 將原消息放入輪次函數 R(k n , m) 進行獨立加密計算,每次計算把擴展出來的輪次密鑰 k n 及消息狀態 m 作為輸入,總共進行 10 次。

因為 AES 只能用在 128 位的消息上,因此我們把輸入的消息 m 表示成 4x4 矩陣的單字節單元,同時也能把輪次密鑰 表示成 4x4 的矩陣,這樣就可以對消息及其中間狀態進行異或運算了。

科普 | 密碼學極速入門,Part-1

首先,輸入的消息和第一個輪次密鑰進行 XOR ,再通過字節替代( ByteSub )、行位移( ShiftRows )、列混淆( MixColumns )等運算,輸出轉變後的消息狀態作為結果(這些步驟會在後面做解釋)。接著我們使用不同的輪次密鑰重複上述這些步驟 10 次,唯一的不同點在於最後一次的計算不包含列混淆( MixColumns )。最終的消息狀態和第十一個輪次密鑰(k 10 )進行異或計算,得到最後的輸出。下面簡述了每一輪次的計算中包含的三種步驟:

字節替代( ByteSub ):根據替換表,將消息狀態矩陣中的每一個字節,替換為相應的字節。

科普 | 密碼學極速入門,Part-1

-在 AES 使用的替換表中,每一個字節單元以 16 進製表示。如,字節 9a 會替換為 b8 -

行位移( ShiftRows ):定量移動每一行。第一行不移動,第二行左移一位,第三行左移兩位,第四行左移三位。

科普 | 密碼學極速入門,Part-1

列混淆( MixColumns ):對消息狀態中每一列進行線性變換。

目前為止,我們已經能使用 AES 來加密數據。然而,你可能很快能發現 AES 的侷限性——沒辦法在只用一次 AES 的情況下,對超過 128 位(或 16 字節)的消息進行加密。要對超過 16 字節的消息進行加密,我們需要引入 模式加密( Modes of operation ) 概念。


分享到:


相關文章: