C語言揭祕二戰德軍的頂級加解密技術——恩格瑪機!

/ / 恩格瑪機- 原理篇 \ \

非我德軍不善戰,奈何盟軍有圖靈

       二戰戰場上除了有紛飛的戰火,還有科學家們在後方展開的鬥智鬥勇的密碼戰,而圖靈破解了德國納粹恩格瑪密碼機更是對德國納粹的致命一擊,直接加速了二戰的勝利。(電影《模仿遊戲》講的就是這段歷史,有興趣的朋友可以瞭解一下。)

       恩格瑪”(Enigma,謎)密碼機是二戰時期的納粹德國及其盟國,特別是德國軍方所使用的一種高級機械加密系統,以轉子結構爲主體。密碼機一般裝在一個盒子裏。

       今天小編就和大家一起探討一下恩格瑪機如何用c語言實現。

       想要理解恩格瑪機是如何運行的,首先要理解這種機器的加密原理。雖然恩格瑪機看起來複雜,但它進行加密的基本原理並不複雜。這種機器所做的本質上是一種替換加密(Substitution Cipher)

       不要被這個名字嚇倒,我們首先來看一下替換加密是什麼東西。

 

/ / 替換加密 \ \

       替換加密,又名取代加密,顧名思義,意爲使用密文字母代替明文字母的位置,加密結束後,將會得到一段不經解密誰也看不懂的密文。聽起來是不是很簡單,讓我們一起來看一個例子:

       首先給定簡單替換加密的一個替換密碼錶

       如果我們想使用上面的替換密碼錶將 hello進行加密,只需要查詢替換密碼錶,進行逐個替換即可。

       因此HELLO加密後的密文就是URYYB。解密的時候同樣根據替換密碼錶替換回原來的明文(是不是很簡單)。

       如果直接使用暴力破解,26個字母的排列順序有26!= 403291461126605635584000000 這麼多種可能,這意味着如果全世界60億人每人每秒可以測試一種可能的密碼錶,也需要21億年才能試完所有的排列組合。事實上很長一段時間,這種簡單的替換密碼,被認爲相當安全。

       直到。。。。

       有人用語言學和統計學的武器攻破了單表替換加密的大門。

       在使用字母文字的語言中,單個字母在普通文本中使用的概率是各不相同的,以英語爲例,下面是摘自維基的英語文本中典型的字母分佈情況

       仔細觀察上圖,上圖中每個字母出現的頻率都各不相同。

       我們剛剛使用的單邊替換加密中,雖然每個字母都已經改頭換面變成另一個字母,但是這並不能改變它在一段文本中出現的頻率。因此我們完全可以統計密文中各個字母的出現頻率,並試圖猜測單表替換密碼錶(本質上就是建立一一映射關係),這樣就能大大的減少要測試的排列數,進而完全破解密文。

       至此,我們上面介紹的單字母表替換加密被無情的破解了。於是不死心的密碼學家們又發明了多字母替換密碼

       下面的內容逐漸進入燒腦狀態,建議大家在頭腦清醒時食用。

 

/ / 多字母替換加密 \ \

       單字母替換密碼的一個致命缺陷就是明文中每一個字母都被唯一的替換爲密文中的另一個字母(建立的一一映射關係不會發生改變)。

       破解者正是抓住了這個漏洞,結合語言學規律,對截獲的密文進行字母頻率分析,找到了這種一對一的替換關係,最終打敗了密碼學家們。

       在這個時候,頑強的密碼學家們並不認輸,誰規定只能使用一個密碼錶了,一個不行就用多個。讓我們再舉個例子:

       以二張密碼錶替換爲例,首先給定二張密碼錶替換加密的替換密碼錶

       與剛剛的單字母替換加密相比,我們又增加了一行密碼錶,有了這兩行密碼錶,我們就可以在加密過程中對明文中的第1個字母使用密碼錶1進行加密,對第2個使用字母使用密碼錶2進行加密,第3個字母又重新使用密碼錶1加密,第4個字母使用密碼錶2,如此重複直到所有明文都被加密。

       大家可以試着用上圖中多字母密碼錶加密下面這句話:

WHEN YOU ARE FREE

       注意到什麼特別之處了嗎?

       這句話中的第3個E會被替換爲U,但是第10個字母同樣是E,卻會被替換爲L,同一個明文字母由於位置的不同而被替換爲不同的密文字母。也就是說,多字母替換密碼不但可以替換掉明文中的字母,同時可以掩蓋文中字母的出現頻率。從而使破解使用的字母頻率分析法立刻失效。

       密碼學家們很是得意,他們繼續問自己,既然可以使用兩行密碼錶,爲什麼不能使用更多密碼錶呢,乾脆讓我們弄個25行的吧。

       上圖就是著名的維熱納爾方陣,是爲了方便加密者進行加密設計的替換密碼錶。

       有了多字母替換,這下密碼學家們再也不用擔心有人能破解了吧!

       讓我們再來看一個例子。

       假設有一個勤勞的密碼學家,爲了得到一份絕對安全的密碼,他不辭辛勞的打算使用7個密碼錶進行加密,假設這位密碼學家打算使用上圖的前7行進行加密。讓我們用這種方法來加密下面這句話。

THE KING ,THE PEOPLE。

       加密後的結果如下圖:

       大家仔細觀察上圖發現了什麼呢?

       沒錯,同樣的單詞the在不同的位置居然被加密成了同一個字符串。原因就在於這個單詞兩個起始位置  mod 7 都是 1,這代表這兩個不同位置的同一個單詞,每個字母加密使用的密碼錶都是同一個,所以加密的結果當然也就相同了。

       破解者就是根據這個特性對重複出現的字母串進行分析,進而推算出密碼學家一共使用了幾個密碼錶進行加密。從而將多表替換降維成單表替換。

       在本例中,根據密文的重複序列很容易猜測使用了7個加密表,這就意味着,明文的第 1、8、15、22...個字母都是使用的同一張密碼錶進行替換,那麼多個密碼錶替換問題又變成了單個密碼錶的替換問題。而上文我們已經發現了單字母表替換是無法抵抗頻率攻擊的。

       面對如此喪心病狂的破解者,無奈的密碼學家們只能仰天長嘆:”除非每加密一個字母就更換一次密碼錶並且永不重複,否則無論如何都逃不過被破解的命運。“

       “每加密一個字母就更換一次密碼錶並且永不重複“ 理論上是可以做到的,只是要加密一份有一萬個字母的明文的話,就需要.... 額,一個長達一萬行的密碼本。這樣就產生了密碼本比密文本身還要長的尷尬局面。並且在軍隊中,每天有成千上萬的信息在各地傳送,如果爲每條信息都創造一個隨機密碼錶的話,如何保存,如何分配都是難以解局的問題。

       顯然,這個任務已經超出了人類力所能及的範圍。

 

/ / 恩格瑪機 \ \

       不過人類做不到,不代表機器也做不到。

       這正是恩格瑪機的過人之處,使用機械原理完成了大量重複有規律的勞動

       (叨叨了這麼久終於講到正題了)

       先上一張圖看看恩格瑪機的構造:

       上面這張圖中可以看出,恩格瑪機的四個主要部件:

       鍵盤:這個沒什麼好解釋的,輸入明文或者密文用的

       燈盤:在鍵盤上輸入一個字母,燈盤上會有一個字母亮起來,代表鍵盤上輸入的字母加密後的結果。

       轉子:這個是恩格瑪機的核心,是加密元件,後面進行解釋。

       插線板:這是在轉子進行加密後,爲了提高安全性而增加的裝置,不是本文的核心,這裏不再贅述。

       恩格瑪機的偉大之處就在於它在進行高度複雜的加密運算的同時,操作的簡易性也幾乎做到了極致。只需要簡單的從鍵盤輸入,就能從燈盤顯示加密後的輸出結果。真的是小學生都能用。

 

/ / 恩格瑪機 - 轉子 \ \ 

       講完了恩格瑪機我們再來看看恩格瑪機的關鍵元件:轉子

       圖片左邊是一個完整的轉子,右邊是一個轉子拆開後的零件。

       轉子的工作原理其實很簡單,每個轉子額左右兩側各有26個點位,分別代表A-Z 這26個字母。信號從一邊進去,從另一邊出來,但是在製造轉子的過程中,位於轉子左右兩側的26個字母的對應關係被打亂(單個轉子的功能相當於一個單字母替換表):

       下面是兩張側視圖,可以更清楚的看到位於轉子兩側的26個點:

       但是由於單個轉子只能提供一個固定不變的密碼錶。因此並不安全。德國人當然也意識到了這一點,所以他們在恩格瑪機上使用了三個串聯在一起的轉子,如下圖:

       三個轉子的替換就相當於一個三輪替換,但是我們上文已經分析發現,即使是多表替換也並不安全。單純的將三個轉子串聯起來,他們還是隻能提供一個固定不變的密碼錶

       但是,當德國人在這三個轉子上加入一個新的特性後,它就可以做到密碼學家們夢寐以求的每加密一次就換一次密碼錶的效果。這個新特性就是:

       每輸入一個字母以後,第一個轉子就會自動轉一格,當第一個轉子轉完一圈時,會帶動第二個轉子轉動一格。同理,第二個轉子轉動一圈時會帶動第三個轉子轉一格(類似於錶盤上秒針、分針、時針的轉動關係)。

       由於三個轉子每個都有26種可能的位置,所以三個轉子一共可以提供26^3=17576個不同的密碼錶。

       這個數字已經相當可觀了,德國人不滿足於此,又將三個轉子設計爲可以相互交換位置的形式。三個轉子可以有3!= 6種不同的排列方式,所以密碼錶的數目又增加到 17576 X 6 = 105456,也就是大約十萬個。

       但是德國仍然不滿足,又增加了插線板和轉子的數量,將密碼數量進行一步擴大了1000億倍。

       下面是一張圖,表示了信號從被輸入轉子開始,一直到加密完成從轉子中輸出的完整路徑。

       大家可以看到字母A從鍵盤被輸入,依次經過三個轉子加密後到達反射器,然後在反射器這裏又被替換成另一個字母,接下來又沿着轉子返回加密,最終輸出字母G。

/ / 恩格瑪機 - 反射器 \ \ 

       有人會問爲什麼除了轉子,還需要一個反射器?

       事實上,這個反射器的加入賦予恩格瑪機兩個非常重要的性質:

1、反射器使得恩格瑪機的加密過程是自反的。也就是如果輸入A得到G,那麼在機器配置不變時,輸入G一定會得到A。

2、一個字母的加密後的輸出結果絕對不會是自身。

以下是對這兩個性質如何得到的一些說明:

       1)轉子配置不變,意味着字母從同一邊到另一邊走的永遠是一條固定的路徑,意味着上圖中紅色和藍色路徑是固定的,反射器不變,意味着綠色路徑也是固定的。那麼就意味着字母A沿着紅色路線、綠色路線、藍色路線,一定會得到字母G,同理,字母G沿着藍色路線,綠色路線、紅色路線也一定會得到字母A。

       2)性質二我們基於假設考慮一下:假如字母A想讓加密結果是自己,那麼它必須沿着紅色路徑進入,並且沿着紅色路徑返回才行,但是反射器的加入,強制輸入輸出不相等,導致上述條件永遠得不到滿足。

       第二個性質看起來是一個優點,畢竟把一個字母加密成自身不就等於沒有加密嗎?但是這個看似優點的性質日後反而成了恩格瑪機的一個重要漏洞。在破解過程中被破解者狠狠利用了一把。

 

/ / 恩格瑪機 - C語言實現 \ \

       恩格瑪機的原理暫時先講到這,現在讓我們思考一下如何用c語言實現一個簡易的恩格瑪加密機。

       關鍵就在於使用循環模擬轉子旋轉的過程。

       一個簡單的恩格瑪機加解密實現代碼如下,供大家參考:

#include<stdio.h>

#include<stdlib.h>

#include<string.h>

void Enigma(char input[20]){

    int code;

    int n[4] = {24,2,5};  //定義3個轉子

    int nsize=3;

    char output[20];

    for (int i = 0; i < strlen(input);i++)

    {

        if(input[i]==' '){output[i] = ' ';continue;}

        code = input[i]-'a';

        for (int j = 0; j < nsize;j++)

        {

            code = (code + n[j]) % 26;

        }

        if(code%2==0)  code++;else code--;  //反射器如果偶數+1,奇數-1,反射器只要能實現字母兩兩配對就可以了。

        for (int j = nsize-1; j >=0;j--)

        {

            code = code - n[j];

            if(code<0)code=26+code;

        }

        n[0]++;

        for (int j = 0; j < nsize-1; j++)

        {

            if (n[j]>=26)

            {

                n[j + 1]++;

                n[j] = 0;

            }

        }

        n[nsize-1] = n[nsize-1] % 26;

        output[i] = code+'a';

    }

    printf("輸出爲: %s\n",output);

}

int main()

{

char plain[20] = "hey hey  helloworld";

char cipher[20] = "ifz ifx  gdkmpvpske";

Enigma(plain);  //輸入明文計算出密文

Enigma(cipher);  //輸入密文計算出明文

//上述的兩次調用體現了恩格碼機的自反性

return 0;

}

對於熱愛編程的人來說,有一羣一起學習一起解答的小夥伴很重要!筆者有一個C語言/C++編程零基礎入門學習交流俱樂部(點擊進入),還有編程學習文件(源碼,零基礎教程,項目實戰教學視頻),歡迎初學者和正在進階中的小夥伴們!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章