如果讓你來設計消息加密
你是跑碼場的一個程序員,名字叫招財。
利用上班摸魚的時間編寫了一個簡易的即時通訊軟件,并發布到了網上。過了一段時間,你在軟件上突然收到一條私信。
“小哥哥,我很喜歡你寫的這個軟件,我也是程序媛,希望以后能多多和您交流。”
你望了望四周,沒有人表現得異常,于是你確認不是同事在逗自己。
你興沖沖地給對方回復,一來二去,慢慢熟識了起來。你知道了對方的名字,叫小美。
1、不安全的明文
隨著交流的話題越來越深入,你也慢慢變得惶恐。你本來就是隨手寫著玩兒的軟件,消息都是明文發送的,這萬一被研究網絡的同事給監聽了,以后在公司還怎么混?
暴露的明文
于是你想到了:加密。
2、對稱加密
如果雙方擁有同樣的鑰匙,發送消息的一方使用這個鑰匙進行加密,接收消息的一方使用同一個鑰匙進行解密。這么一來,加密的事情就變得簡單了。
為了實現這個功能,你想到了之前學過的異或(XOR)操作,這個操作的規則總結起來就是:相等為0,不等為1。任何數據在計算機中都會最終表示為01的字節流,比如你想發送的消息被最終編碼為1001110011001110,然后隨機生成一個同樣長度的字符串1011011100110011,稱為秘鑰,兩者做一下異或操作:
異或加密
消息明文與秘鑰進行異或操作之后就得到了密文,按照異或運算的性質,如果此時將密文再和秘鑰做一次異或操作,那么將重新得到消息明文。
異或解密
如此一來便實現了雙方使用同一個共享秘鑰對消息進行加密/解密的操作。
但是目前有個問題,你生成的秘鑰長度必須和消息的長度保持一致才能做異或操作,除非你對異或操作進一步封裝。你才懶得琢磨這些東西呢,于是上網找思路。
這才知道,你的想法其實就是對稱加密。DES、3DES以及AES密碼算法都屬于對稱加密,其中或多或少都利用了異或運算的性質,否則就沒有了“對稱”的效果。
你選擇了目前最流行的AES算法,打算直接使用現成的類庫實現加密。你把這個想法告訴了小美,迫不及待地想讓她知道你們的對話已經實現了機密性。
誰知,小美一針見血地指出了問題,“秘鑰如何安全地在我們之間進行共享呢?”
是啊,監聽者也是可以獲取到秘鑰的。這樣就很矛盾,如果有一個辦法能將秘鑰安全地共享出去,那么豈不是也可以用同樣的方法來安全地發送明文咯?
對稱密碼的秘鑰必須發送,而又不能明文發送,這就是對稱秘鑰的配送問題。
秘鑰配送問題
3、非對稱加密
于是你又開始尋找其他方法,終于發現了一種叫做公鑰密碼的算法。
這種算法可以生成一組密鑰對,分別叫做公鑰和私鑰。正如其名字暗示的那樣,公鑰是可以公開的,地球人都可以知道,而私鑰必須自己保存好,打死也不能讓別人知道的。
由公鑰進行加密的密文,必須使用與該公鑰配對的私鑰才能夠解密。反過來,使用私鑰進行加密的密文,擁有公鑰的人都可以進行解密。這個特點非常重要。
于是你生成了一組密鑰對,并將公鑰發給了小美,自己保存好私鑰。你讓小美給你發送消息之前先用你的公鑰對消息進行加密,這樣一來,小美的加密消息只有你的私鑰才能夠解密。
于是便實現了小美對你發送消息的機密性。
消息的機密性
反過來,如果要實現你對小美發送消息的機密性,就需要小美生成一組密鑰對,你獲得小美的公鑰,然后發送消息之前首先用小美的公鑰對消息進行加密,將密文發送給小美之后,小美再用她的私鑰進行解密。
如果通信過程中的公鑰和密文被監聽者獲取到也沒關系,因為你們兩人的私鑰都沒有出現在通信過程中,監聽者即使有了密文也沒法解密。
這樣一來,你通過了公鑰加密解決了消息的機密性和秘鑰的配送問題(因為壓根不需要配送對稱加密的秘鑰了)。
公鑰密碼還有一個名字,叫做非對稱加密。這個名字是相對對稱加密而言的。
對稱加密是使用同一個秘鑰進行相反的運算,因此對稱密碼中的加密和解密就像照鏡子一樣,是相互對稱的。非對稱加密中,加密和解密使用的是不同的密鑰,并非相互對稱,因此稱為非對稱加密。
注:大名鼎鼎的RSA算法和ECC(橢圓密碼曲線)算法都是公鑰密碼算法的具體實現
4、混合加密算法
公鑰加密的改進讓你感到非常踏實,現在滿腦子里裝的都是跟小美聊天。可是你逐漸發現,小美的回復變得比之前慢了一些。
和小美溝通一番之后發現,她對你的回復也有同樣的感覺。
聰明的你最終發現了原因,公鑰加密的算法效率太低下了!在采用具備同等機密性的密鑰長度的情況下,公鑰加密的速度只有對稱加密的幾百分之一。
知道了問題,解決方案也是很明顯了,把對稱加密和公鑰加密結合起來使用,也就是混合加密。
既然是混合加密,自然既要傳送消息,又要傳送對稱加密的秘鑰。你先用加密效率很高的對稱加密算法對消息進行加密,這樣就實現了消息的機密性。接下來只要保證對稱加密秘鑰傳輸的機密性就可以了。
這時候又要用到公鑰加密了。你將對稱加密的秘鑰當做消息,利用上文公鑰加密的步驟,先使用小美的公鑰對對稱加密的秘鑰進行加密,小美收到之后再用自己的私鑰進行解密,就能安全在你倆之間傳遞對稱加密的秘鑰了。
你也不用擔心效率問題,畢竟對稱加密的秘鑰通常比消息短得多,況且秘鑰的傳遞只需要一次就可以了,因此加密的時間代價可以忽略。
畫一下使用混合加密算法時,你發送消息進行加密的流程圖。
混合加密
懂了加密,解密也就很簡單了,為了讓小美看得明白,你還是給她畫了個解密流程圖。
混合解密
到此為止,你解決了公鑰加密速度慢的問題,并通過公鑰加密解決了對稱秘鑰的密鑰配送問題。
5、誰改了我的消息
你和小美聊得愈發火熱。但是你最近總是時不時收到小美發過來的莫名其妙的文字。你開始不以為意,但是這種文字的發送頻率越來越高,實在搞得你頭大。
你趕緊問了問小美,在確定不是她故意發這種文字之后,你明白了。
你倆被人盯上了。。。

你分析了一下小美實際傳給你的加密消息與你實際收到的加密消息,發現編碼之后的數據有兩位比特被改變了。改變雖然不大,但是對消息的可讀性會造成相當大的影響。
你遇到中間人攻擊了。
這種情況下,中間人不需要知道你倆聊得究竟是什么,只需要截取你們的消息,然后進行隨意篡改,就能擾亂你倆之間的正常交流。
你不禁感嘆:怎么傳遞個消息就這么難呢!
好在這個問題不難解決,你馬上就想到了單向散列算法。
單向散列算法可以對任意長度的消息生成一個固定長度的一串數據(散列值),這串數據的長度遠小于輸入的消息長度,因此又被稱為消息摘要,單向散列算法也因此被稱為消息摘要算法。
摘要算法可以實現消息的完整性檢查。
單向散列函數
消息摘要算法的一個巨大好處是對消息的變化極為敏感,哪怕對消息僅修改了1個比特,生成的消息摘要也會有翻天覆地的變化。而且,即使中間人截獲了摘要消息,他想自己偽造一個經過散列能夠生成同樣摘要的消息幾乎是一件不可能的事情。
注:經常聽到的MD5、SHA-1、SHA2、SHA3算法都是消息摘要算法的具體實現
于是你在消息發送和解析過程中又添加了對消息摘要算法的支持。發送數據之前,先對混合算法加密之后的密文計算摘要值,然后將摘要值附在密文的最后,一起傳輸給小美。
圖片
小美收到數據后,根據信息摘要的固定長度,首先分離摘要值和密文,然后使用相同的摘要算法計算出密文的摘要,與接收到的摘要進行對比,一致則表示信息沒有被篡改,否則就說明被動了手腳,直接丟棄。
圖片
你認為事情到這終于結束了。但是軟件更新之后,你發現還是會時不時收到莫名其妙的消息。
6、是誰在冒充
你思來想去,問題到底出在了哪里?
“會不會是我們的消息整個都被篡改了啊。”小美說道。“如果中間人監聽到了整個消息,分離出了混合加密的密文和摘要值,然后篡改混合加密的密文,再重新對篡改之后的密文計算出一個新的摘要,附在篡改的密文之后再發送,我們根本無法識別出篡改。”
中間人攻擊
是啊,如果真的是這樣,摘要值檢查的實際上就是中間人發送的消息的完整性,這個檢查就失去了意義。
現在中間人已經徹底挾持了通信線路,只要中間人想,他就能篡改你們之間的所有數據。換句話說,你現在根本不知道和你進行通信的是小美還是中間人。
這就是單向散列函數的缺陷,能夠辨別出“篡改”,但是無法分辨出“偽裝”。
你現在需要實現消息的認證功能。也就是說,你對小美發送的消息,需要向小美證明消息確實是你發的,并且沒有被篡改。同樣,小美對你發送的消息,也需要向你證明,消息確實是小美發的,并且沒有被篡改。
7、確認對方身份
于是你跟小美商量,需要約定一個只有你們兩人才知道的「信息」,并且通過接收到的消息可以判定,只有擁有這個共同信息的彼此才能發出這條消息。
小美立刻想到,“我們一直在使用的對稱加密的秘鑰不就是這個「共同信息」嘛!如果我發的消息你能解密出來,不就證明我就是我了嗎?”
“你這么想從一定程度上是對的,但是有個前提條件,就是你發的消息一定是有意義的。如果你本身就是想給我發送一堆亂七八糟的文字,我無法確定這是你的本意,還是說消息已經被中間人篡改了。”
你倆陷入了短暫的沉默。
你思考了一下,摘要值目前無法發揮認證的作用是因為只要中間人獲取到了密文,就能隨便生成摘要值。那如果給摘要值的生成提高門檻,只有擁有「共同信息」的彼此才能夠生成正確的摘要值,這樣的話不就能認證了嘛。
這個摘要值就叫做消息認證碼。
網上搜索了一番,還真有這種方法,叫HMAC(Hash Message Authentication Code,哈希消息認證碼),是用單向散列函數來構造消息認證碼的一種方法。
單向散列與HMAC
摘要值和HAMC值的最主要的區別就是后者在進行單向散列的時候,需要用到一個秘鑰。因此這個可以簡單理解為,消息認證碼是一種與秘鑰相關聯的單向散列函數。
有了這個技術,再來看一下你給小美發送消息的過程。
消息認證碼
本來應該為HMAC單獨生成一個隨機秘鑰,但是又會涉及到秘鑰配送的問題。由于我們之前已經使用公鑰解決了秘鑰配送問題了,為了方便,就直接使用對稱秘鑰作為HMAC的秘鑰了。
和原來不同的是,用計算出的MAC代替了原來的摘要值,小美接收到密文和摘要值之后。利用自己的私鑰解密獲得對稱加密的秘鑰,再利用這個秘鑰對收到的密文計算MAC值,如果兩個MAC一致,那么小美就可以確定這個消息是你發送的,沒有經過中間人篡改。
如此一來,使用MAC值就實現了消息的完整性校驗和身份認證的功能。
8、對方死不認賬了
突然有一天,小美對你發來了一條消息。
“PHP是世界上最好的語言~”
你當場炸裂啊~說這話妥妥引戰嘛,你剛要和小美理論一下,小美緊接著來了句:“我跟你玩個游戲啊。”然后又發送了一個調皮的表情。“你如何證明我對你說了這句話呢?”
“這還需要啥證明啊,我用咱倆共享的秘鑰,生成了MAC值,然后和你發給我的MAC對比,是一致的。如果你的私鑰沒有泄露,我就敢絕對保證,這條消息就是你發的!”
“沒錯,在咱倆之間,是絕對能保證身份的認證的。但是我的問題是,你如何向其他人證明這個消息是我發送的呢?你想啊,你和我有相同的秘鑰,也就是說,理論上這條消息你也能生成。我要是死不認賬,你怎么辦?當然咯,截圖可不算哈~”
小美說得沒錯,按照現在的加密設計,的確沒法向第三方證明她說過的話。
現在你倆之間能相互認證是由于擁有同一個秘鑰,你確定不是自己發的,那必然就是對方發的。如果想向第三方證明消息是小美發的,那就必須使用小美獨有的信息對消息做一下處理。
就好比古代的虎符,如果小美持有其中一半,并且保證私有,這樣不管另一半在誰的手里,只要兩部分能夠合二為一,就能確認對方就是小美。
驗證虎符
這不就是公鑰和私鑰嘛!
小美用自己的私鑰對消息計算出一個「簽名」,任何持有小美公鑰的人都沒辦法用公鑰復刻這個簽名,但是可以對小美發送的簽名用公鑰進行解密,解開的內容如果恰好就是消息本身,那說明收到的消息一定屬于小美!畢竟私鑰是獨一無二的,這下子小美就再也沒辦法否認了!
但是有個小問題,公鑰加密的效率實在是太低了,如果對整個消息使用私鑰進行加密,耗時太久。能不能找個比較短的數據來代替消息本身呢?
老朋友——單向散列函數,又該出馬了。只要先用單向散列函數求出消息的散列值,然后使用私鑰對散列值進行簽名就可以了。散列值可比消息本身短得多,因此對其進行簽名的時間代價就小得多了。
數字簽名
如果中間人篡改了小美發送的消息,那么你計算出來的散列值就會發生變化,導致簽名驗證失敗,簽名保證了消息的完整性和對方身份的認證。不僅如此,簽名還能防止小美否認之前發的消息。
從圖中可以看出,簽名已經徹底替換掉了之前使用的消息驗證碼。
到此為止,你已經實現了消息的機密性、完整性、身份認證以及不可否認性。
居然不知不覺已經走了這么多路,你不禁問自己,到簽名這一步已經完美了嗎?簽名的驗證依賴于消息發送者公開的公鑰,那如果從一開始,這個公鑰就被中間人劫持,換成了中間人自己的公鑰了呢?我們又該如何確保收到的公鑰沒有被篡改呢?
公鑰傳輸不安全
9、CA機構與證書
你發現自己陷入了一個怪圈。數字簽名是用來進行身份認證、防止篡改以及防止否認的,數字簽名依賴公鑰的傳遞,公鑰的傳遞又需要進行身份認證以及防止篡改。。。
你把現在的設計告訴了小美,想看看她還有沒有其他的主意。
“我覺得你現在設計地已經夠好了,接下來已經不是單純的軟件設計能力能夠解決的事情了,已經上升到社會學層次的高度了。”
“這是什么意思?”
小美解釋道:“就是說,我們應該成立類似于公證處這樣的專業機構,來認證公鑰的合法性,叫做CA。認證機構也要生成自己的一組密鑰對,分成公鑰和私鑰,私鑰自己保管,公鑰任何人都可知。”
“那這怎么進行認證呢?”
“還是用你數字簽名的思路,比如我在分發我的公鑰讓你知道之前,我先把公鑰發給認證機構,然后認證機構用自己的私鑰對我的公鑰添加數字簽名,最后頒發一個包含我的公鑰和認證機構數字簽名的證書。這個證書就證明我的公鑰是合法的。”小美補充道,然后畫了個圖。
公鑰的證書
你一眼就看出了這個邏輯的漏洞,這個方案沒有從根本上解決問題,只是把問題轉移了而已。因為小美媽媽這個認證機構需要對小美的公鑰施加數字簽名,你勢必需要用到小美媽媽這個認證機構的公鑰。
“我現在不信任你的公鑰,也對你媽媽這個認證機構的公鑰有所懷疑,那認證機構對頒發的證書就沒有任何意義!依舊是個死循環!“你對小美提出了自己的疑問。
”那取決于你怎么理解『信任』這個詞兒了,如果你除了自己誰也不信,那對你來說永遠不會有安全的通信,這個邏輯鏈條就是個死循環。實際上,『信任』這個詞兒是比較出來的,在多個供選擇的信任對象中只要有一個你最信任的就可以了“。
小美繼續說:”我舉個例子。你覺得銀行愿意把錢借給你是因為信任你這個人本身嗎?當然不是,銀行相信的是你背后抵押的房子等所有值錢的東西。回到這個例子里,如果我媽媽的認證機構經過層層關系,最終找到了你媽媽的認證機構,你看看這個邏輯是不是就解釋的通了。“
圖片
信任鏈
你看了一下這個層級,既然是你媽媽開的認證機構,你肯定選擇信任,由于「招財媽媽認證機構」出具了「小美媽媽認證機構」公鑰的證書,「小美媽媽認證機構」又出具了小美公鑰的證書,根據這個信任鏈條,你自然就信任小美的公鑰的合法性了。
到此,問題全部解決。