古老的加密技術

hsy0發表於2019-01-17

看看在歷史上我們是如何隱藏私密資訊的

凱撒加密

第一個被最廣泛熟知的加密方式就是公元前 58 年的凱撒加密(Caesar cipher)

加密

凱撒加密的加密方式就是,在加解密之初,加解密的雙方需要先確定一個位移長度。加密的一方通過對明文中的單詞按照選定的平移長度逐個的進行平移,得到加密後的內容;解密的一方通過將密文按照選定的平移長度進行逆向的平移,則可以得出明文。

比如,對於加密條件 明文為 hello,平移長度為 3 的加密過程:

  1. 根據 26 個英文字母的順序,h 向後推 3 個的字母為 k
  2. 按照第一步對剩餘的明文字母依次類推,可以得出密文為 khoor

破解

對於凱撒加密,其破解的關鍵有兩點:

  1. 明文所採用的語言中的字母出現頻率的統計圖表(可以通過大量的統計分析該語言的書籍)
  2. 對密文進行大量統計得出的其中其母出現的頻率圖表
  3. 第1步和第2步得出的圖表進行簡單的位移就可以得知加密採用的位移

之所以可以這樣去破解凱撒加密,是因為人類的語言實際是一個具有規律的事物,而語言中的各個字母出現的頻率也是這個規律的一部分(這一點常常容易被忽略)。對於選定的位移,實際上只是將原有的字母頻率圖表做了一個平移 - 因為每一個字母都平移了固定的長度。

多字碼加密

15 世紀中葉,加密方式進步到了多字碼加密(Polyalphabetic Cipher)

加密

多字碼加密的加密方式就是,在加密之初,加解密雙方要先確定一個平移詞(shift word)。加密的一方首先需要事先將確定的平移詞轉變成與其對應的一組數字(稱為字碼序列),然後對於給定的明文,不斷地按照轉換後的一組字碼序列的長度,迴圈的對其平移。解密的一方首先也需要將平移詞變成其對應的字碼序列,然後對於給定的密文,不斷地按照轉換後的字碼序列的長度,迴圈的對密文字母其進行逆平移。

比如,對於加密條件 明文為 hello,平移詞為 hi 的加密過程:

  1. 首先將平移詞 hi 變成一組對於的數字,這裡按照英文中 26 個字母的出現順序,平移詞 hi 其中的字母換換後所對應的一組數字就是 78(從 0 開始)

  2. 現在需要根據轉換後的一組平移數字,逐個迴圈的對明文進行平移。

    h e l l o
    + + + + + (按照明文字母在 26 個字母中出現的順序進行平移)
    7 8 7 8 7
    -----------
    o m s t v 
    複製程式碼
  3. 最終,根據上面的變換,就會得出密文 omstv

對於解密的一方,他需要知道平移詞 hi,當然這個雙方在事先就約定好了。解密方式就不冗述了,就是其加密的逆過程。

破解

相對於凱撒加密的破解過程 - 分析統計密文中的字母頻率出現的圖表,與明文所採用的語言中字母出現的圖表進行簡單的平移對比之後,就會得出平移量而言,多字碼加密加大了從密文中得出有效的字母出現的頻率的難度。但是其解密的原理依舊不復雜。

對於破解者而言,他們更加關心的是多字碼加密時採用的字碼序列的長度,比如上面的例子中 78 這個字碼序列的長度就是 2。另外,之所以在上文的加密的過程的解釋中,一直強調 “迴圈” 這個概念的目的就是,當你理解了 “迴圈” 的概念之後,你會發現,上面的例子中 h第一個 lo 都是採用的 7 作為了它們的平移量,那麼問題其實又回到了凱撒加密。

於是,對於破解者,他們只要不斷地猜測字碼的長度,因為明文是按照字碼序列的長度迴圈平移的,一個迴圈的開頭,和下一個迴圈的開始必定是使用的同樣的平移量,只要按照這個規律,將以一個猜測的字碼序列的長度為間隔的加密字母挑出來進行頻率分析統計,然後與明文的字母頻率進行對比,就能得出平移量了 - 回到了凱撒加密的破解過程。

一次一密

19世紀末期,出現了一個具有相當強度的加密方式,稱為一次一密(one-time pad)。

加密

所謂一次一密,其加密的字碼的長度不再像是上文提到的固定長度了,它所採用的是使用隨機的方式得到一個與明文字母等長的隨機字碼序列。

首先要知道的是,對於英文字母而言,每一個字母所能進行的平移量只有 26 種。因為對於任何一個具有固定長度的計數系統而言(其實就是一個模系統),超過了其模的平移將會從頭開始進行移動(補數),這裡你可以想象成一個有 26 個小時刻度的時鐘,從 0 點順時針的平移量如果是 27 的話,實際的結果就是 1 點 - 和順時針直接平移 1 沒有什麼區別。

那麼,對於明文為 hello 的一次一密的加密過程可以是這樣:

  1. 隨機得到一個 0~25 以內的隨機數,假設本次隨機數是 3

  2. 記錄這個隨機數

  3. 將明文 h 平移 3 變成 k

  4. 隨機得到一個 0~25 以內的隨機數,假設本次隨機數是 5

  5. 記錄這個隨機數

  6. 將明文 e 平移 5 變成 j

  7. 依次類推...

那麼假設隨機的字碼序列是 35685,其對應的密文就是 kjrtt。 如果再次加密的話,需要再次隨機生成一個與明文等長的字碼序列。

當然,接收方需要同時知道每一次的隨機字碼序列和對應密文。

破解

對於採用一次一密的加密方式等到的密文,破解者需要面對兩個問題:

  1. 用於加密的字碼序列的長度是和明文等長的,於是也就沒有了 “多字碼加密” 中的 “迴圈” 問題了。
  2. 密文中的每一個字母的出現頻率將會是相同的,因為每個明文字母都隨機對應到了 26 個字母中的一個,它們出現的概率是相同的。

由於密文沒有規律可循,破解者只有通過暴力破解的方式去嘗試得出明文。不過,對於明文 hello 它的密文將會是 26*26*26*26*26 = 11881376 種組合中的一種,而且這僅僅是隻有 5 個字母的情況。

完美保密

理解這樣一個遊戲:Eve 邀請 Bob 來到一個房間,Bob 發現這個房間除了有一副牌、幾把鎖(帶鑰匙的鎖和密碼鎖)、一個空格子之外,什麼也沒有。Eve 讓 Bob 選擇一張牌,然後盡他最大的能力去將牌藏起來。規則很簡單,Bob 不能從房間帶走任何物品,所有牌和鑰匙必須留在房間內,並且在空格子中最多隻可以放一張牌,Eve 保證他沒有動過那些鎖。如果 Eve 不能找出 Bob 藏的牌的話,Bob 就贏了。那麼 Bob 應該怎麼做?

首先 Bob 選擇了一張方塊6,並將它扔進了空盒子中,然後他開始考慮使用哪一個鎖將盒子鎖起來。似乎使用密碼鎖是一個很好的選擇,不過 Bob 很快意識到一個問題 - 桌上剩餘的牌會暴露他的選擇。鎖只不過是一個陷阱,他不能將牌從牌堆裡面拿出來,所以他將選擇的牌重新放回牌堆,並將牌堆進行重新的洗牌,以此打亂它們原有的順序。現在,Bob 選擇的牌,可能是牌堆中的任意一張了,他可以信心十足的離開房間。

最後,Bob 贏得了遊戲,因為 Eve 最多隻能靠猜測才能得知 Bob 選擇的牌 - Bob 沒有留下任何關於其選擇的牌的資訊。即使給了 Eve 一個沒有效能限制的計算機,他也只能靠猜,這就是我們所說的 “完美保密” 。

在 1945 年九月一日,29歲的 Claude Shannon 釋出了一個保密論文,第一次從數學角度去證明 “一次一密” 如何以及為什麼具有完美的保密性。Claude Shannon 是按照下面的方式去思考加密方案的:

  • 設想 Alice 給 Bob 寫了一個 20 個字母長度的訊息。這就好比從訊息空間(message space)中抽出一個特定頁面。對於訊息空間,可以想象成是包含 20 個字母可以組成的所有組合的一個集合。

  • 接著 Alice 需要在 0~25 之間隨機的生成 20 個字母的密匙(字碼)。密匙空間(key space)就是包含所有隨機組合情況的一個集合,所以生成一個密匙就好比從密匙空間中隨機的抽出一頁。

  • 接著 Alice 將密匙的作為一個個平移量應用到明文訊息中,得出了密文。密文空間(ciphertext space)表示了所有可能的加密結果組合的集合。當她選擇並應用了某一個密匙,結果將會唯一地對應到密文空間中的一頁。

  • 注意這裡的訊息空間大小、等於密匙空間的大小、等於密文空間的大小,這些就是 “完美保密” 的定義。所以當只知道密文的情況下,唯一可以得到的資訊就是:這段密文唯一對應於訊息空間中的一頁。因為要破解只能靠猜測,所以無論功能多強勁的計算機,面對只能靠猜測的演算法,除了可以縮短猜測的時間之外,並沒有什麼提升。

現在,在使用一次一密的情況下,唯一需要面對的問題就是,我們如何在事先共享那些長的密匙。

偽隨機數生成器

當我們在觀察自然界時,我們到處會發現一些隨機的波動。我們可以通過對熟知的比如噪音的波動,去測量並生成真實的隨機數。當我們在對噪音進行取樣的時候,我們可以獲得數字。比如,我們通過測量一段時間的電視機電流,我們就可以生成一個真的隨機數序列。為了將一個數的序列視覺化,我們可以根據序列中的每一個數去畫出它們的更改路徑,這種方式也叫做隨機遊走(random walk)。根據視覺化後的影像得出,在真隨機序列中的任意一點上,都無法預測下一點將會出現在哪裡。隨機的過程按理說應該是具有非確定性的,因為它們無法事先就測定。

另一方面,機器是具有確定性的,它的操作是可預測的以及可重複的。由於隨機數需要被不斷以及快速的得到,加上之前的計算機具有有限的儲存大小,所以直接儲存一個固定長度的隨機數是不現實的。所以,在早期的計算機中,科學家發明了一個演算法去機械的模擬隨機中的亂序現象。這個演算法叫做 平方取中 Middle-square method

比如,要使用此演算法去生成一個 4 位的偽隨機數,就需要先選擇一個四位數作為整個過程的起始值(種子),將這個四位數和自身相乘(平方)運算後,會得到一個 8 位的數字(如果不足八位,就在前面補上 0,以湊足 8 位)。得到結果的 8 位數字之後,取出其中間的 4 位數字作為結果,或者作為下一次運算的種子、配合重複上面的過程以獲得更多的 4 位偽隨機數。

為此方法提供隨機性的唯一保障就是最初選擇的隨機種子。相同的種子,將會生成相同的序列。那麼,隨機序列和偽隨機序列之間有什麼不同?可以通過上述提到的隨機遊走的方式將偽隨機序列進行視覺化,以此具象化地進行觀察。結果就會發現,如果中間產生了一個曾經使用過的種子,那麼接下來的結果都將會和之前出現的中間結果發生重複。在偽隨機數序列發生重複之前的時期,就被稱為週期(the period)。這個週期會被最初選擇的種子長度嚴格限制。比如,我們使用了一個 2 個數字的種子,那麼在結果序列發生重複前,可以產生 100 個 2 位數字組合,一旦其中出現了和最初的 2 個數字的種子一樣的中間結果,那麼接下來的中間結果將會做週期性的重複。3 位數字的種子,就可以產生 1000 個 3 位數字的組合。4 位數字的種子,就可以產生 10000 個 4 位數字的組合。如果我們使用了一個具有非常長長度的種子,那麼就可以產生具有非常長週期的偽隨機的結果序列。

另外一個需要面對的問題就是,一旦我們選擇了偽隨機的方式生產隨機數,那麼就會丟失很多在真隨機序列中應該出現的序列。比如,Alice 需要為 20 個字母長度的明文生成一個真隨機 20 個字碼的組合,那麼這些隨機字碼的組合就有 26^20 次方的可能性, 這將會是一個天文數字。作為對比,假設 Alice 使用的是上面提到的偽隨機方式,並使用了一個 4 位的種子。也就是說,使用偽隨機的方式,她只能選擇 10000 種可能的種子,因此只能生成 10000 種不同的數字序列,我們可以在生成的序列中選擇前 20 個作為字碼。可以發現,使用了偽隨機方式的結果,使得我們的密匙空間被大大的縮小了,密匙空間的太小變成了種子空間(seed space)的大小。

那麼作為這種偽隨機的破解方式,可以通過不斷的猜測所有的可能的種子。這就將問題帶到了一個計算機中常見的問題 - 什麼是可能的,以及什麼是在一定時間內可能的。當我們在買一個自行車密碼鎖時,其實採用了相同的邏輯。我們知道所有人都可以對密碼鎖去嘗試所有可能數字組合,直到他們找出匹配的那一組並開啟了鎖。但是,這個過程可能將花費他們幾天的時間,所以對於 8 個小時之內的時間,我們可以認為鎖幾乎是安全的。在上述偽隨機生成方法下,保密程度將隨著種子的長度而提高,如果最強勁的計算機都需要花幾百年才可以嘗試掉所有的種子的可能性的話,我們就可以認為這種方式幾乎是安全的,但不是完美保密。隨著計算機的不斷髮展,種子的長度也需要相應地不斷地增長。

採用上述的偽隨機方式,使得 Alice 和 Bob 不必事先共享一整個很長的字碼序列了。他們只要分享一個對應的隨機種子,然後使用那個種子去生成看起來是隨機的序列作為字碼序列。但是,當他們無法面對面分享那個隨機種子時,將會發生什麼?

相關文章