1. 程式人生 > 實用技巧 >加密演算法的前世今生

加密演算法的前世今生

-----------

說到密碼,我們第一個想到的就是登陸賬戶的密碼,但是從密碼學的角度來看,這種根本就不算合格的密碼。

為什麼呢,因為我們的賬戶密碼,是依靠隱蔽性來達到加密作用:密碼藏在我心裡,你不知道,所以你登不上我的賬戶。

然而密碼技術認為,「保密」資訊總有一天會被扒出來,所以加密演算法不應該依靠「保密」來保證機密性,而應該做到:即便知道了加密演算法,依然無計可施。說的魔幻一點就是,告訴你我的密碼,你依然不知道我的密碼。

最玄學的就是 Diffie-Hellman 金鑰交換演算法,我當初就覺得很驚奇,兩個人當著你的面互相報幾個數字,他們就可以擁有一個共同的祕密,而你卻根本不可能算出來這個祕密。下文會著重介紹一下這個演算法。

本文討論的密碼技術要解決的主要是資訊傳輸中的加密和解密問題。要假設資料傳輸過程是不安全的,所有資訊都在被竊聽的,所以傳送端要把資訊加密,接收方收到資訊之後,肯定得知道如何解密。有意思的是,如果你能夠讓接收者知道如何解密,那麼竊聽者不是也能夠知道如何解密了嗎?

PS:我認真寫了 100 多篇原創,手把手刷 200 道力扣題目,全部發布在 labuladong的演算法小抄,持續更新。建議收藏,按照我的文章順序刷題,掌握各種演算法套路後投再入題海就如魚得水了。

下面,我們會介紹對稱加密演算法、金鑰交換演算法、非對稱加密演算法、數字簽名、公鑰證書,看看解決安全傳輸問題的一路坎坷波折。

一、對稱性加密

對稱性密碼,也叫共享金鑰密碼,顧名思義,這種加密方式用相同的金鑰進行加密和解密。

比如我說一種最簡單的對稱加密的方法。首先我們知道資訊都可以表示成 0/1 位元序列,也知道相同的兩個位元序列做異或運算的結果為 0。

那麼我們就可以生成一個長度和原始資訊一樣的隨機位元序列作為金鑰,然後用它對原始資訊做異或運算,就生成了密文。反之,再用該金鑰對密文做一次異或運算,就可以恢復原始資訊。

這是一個簡單例子,不過有些過於簡單,有很多問題。比如金鑰的長度和原始資訊完全一致,如果原始資訊很大,金鑰也會一樣大,而且生成大量真隨機位元序列的計算開銷也比較大。

當然,有很多更復雜優秀的對稱加密演算法解決了這些問題,比如 Rijndael 演算法、三重 DES 演算法等等。它們從演算法上是無懈可擊的,也就是擁有巨大的金鑰空間,基本無法暴力破解,而且加密過程相對快速

但是,一切對稱加密演算法的軟肋在於金鑰的配送。加密和解密用同一個金鑰,傳送方必須設法把金鑰傳送給接收方。如果竊聽者有能力竊取密文,肯定也可以竊取金鑰,那麼再無懈可擊的演算法依然不攻自破。

所以,下面介紹兩種解決金鑰配送問題最常見的演算法,分別是 Diffie-Hellman 金鑰交換演算法和非對稱加密演算法。

二、金鑰交換演算法

我們所說的金鑰一般就是一個很大的數字,演算法用這個數加密、解密。問題在於,通道是不安全的,所有發出的資料都會被竊取。換句話說,有沒有一種辦法,能夠讓兩個人在眾目睽睽之下,光明正大地交換一個祕密,把對稱性金鑰安全地送到接收方的手中?

Diffie-Hellman 金鑰交換演算法可以做到。準確的說,該演算法並不是把一個祕密安全地「送給」對方,而是通過一些共享的數字,雙方「心中」各自「生成」了一個相同的祕密,而且雙方的這個祕密,是第三方竊聽者無法生成的

也許這就是傳說中的心有靈犀一點通吧。

這個演算法規則不算複雜,你甚至都可以找個朋友嘗試一下共享祕密,等會我會簡單畫出它的基本流程。在此之前,需要明確一個問題:並不是所有運算都有逆運算

最簡單的例子就是我們熟知的單向雜湊函式,給一個數字 a 和一個雜湊函式 f,你可以很快計算出 f(a),但是如果給你 f(a)f,推出 a 是一件基本做不到的事。金鑰交換演算法之所以看起來如此玄幻,就是利用了這種不可逆的性質。

下面,看下金鑰交換演算法的流程是什麼,按照命名慣例,準備執行金鑰交換演算法的雙方稱為 Alice 和 Bob,在網路中企圖竊取他倆通訊內容的壞人稱為 Hack 吧。

首先,Alice 和 Bob 協商出兩個數字 NG 作為生成元,當然協商過程可以被竊聽者 Hack 竊取,所以我把這兩個數畫到中間,代表三方都知道:

現在 Alice 和 Bob 心中各自想一個數字出來,分別稱為 AB 吧:

現在 Alice 將自己心裡的這個數字 AG 通過某些運算得出一個數 AG,然後發給 Bob;Bob 將自己心裡的數 BG 通過相同的運算得出一個數 BG,然後發給 Alice:

現在的情況變成這樣了:

注意,類似剛才舉的雜湊函式的例子,知道 AGG,並不能反推出 A 是多少,BG 同理。

那麼,Alice 可以通過 BG 和自己的 A 通過某些運算得到一個數 ABG,Bob 也可以通過 AG 和自己的 B 通過某些運算得到 ABG,這個數就是 Alice 和 Bob 共有的祕密。

而對於 Hack,可以竊取傳輸過程中的 GAGBG,但是由於計算不可逆,怎麼都無法結合出 ABG 這個數字。

以上就是基本流程,至於具體的數字取值是有講究的,運算方法在百度上很容易找到,限於篇幅我就不具體寫了。

該演算法可以在第三者竊聽的前提下,算出一個別人無法算出的祕密作為對稱性加密演算法的金鑰,開始對稱加密的通訊。

對於該演算法,Hack 又想到一種破解方法,不是竊聽 Alice 和 Bob 的通訊資料,而是直接同時冒充 Alice 和 Bob 的身份,也就是我們說的「中間人攻擊」:

這樣,雙方根本無法察覺在和 Hack 共享祕密,後果就是 Hack 可以解密甚至修改資料。

可見,金鑰交換演算法也不算完全解決了金鑰配送問題,缺陷在於無法核實對方身份。所以金鑰交換演算法之前一般要核實對方身份,比如使用數字簽名。

PS:我認真寫了 100 多篇原創,手把手刷 200 道力扣題目,全部發布在 labuladong的演算法小抄,持續更新。建議收藏,按照我的文章順序刷題,掌握各種演算法套路後投再入題海就如魚得水了。

三、非對稱加密

非對稱加密的思路就是,乾脆別偷偷摸摸傳輸金鑰了,我把加密金鑰和解密金鑰分開,公鑰用於加密,私鑰用於解密。只把公鑰傳送給對方,然後對方開始給我傳送加密的資料,我用私鑰就可以解密。至於竊聽者,拿到公鑰和加密資料也沒用,因為只有我手上的私鑰才能解密。

可以這樣想,私鑰是鑰匙,而公鑰是鎖,可以把鎖公開出去,讓別人把資料鎖起來發給我;而鑰匙一定要留在自己手裡,用於解鎖。我們常見的 RSA 演算法就是典型的非對稱加密演算法,具體實現比較複雜,我就不寫了,網上很多資料。

在實際應用中,非對稱性加密的運算速度要比對稱性加密慢很多的,所以傳輸大量資料時,一般不會用公鑰直接加密資料,而是加密對稱性加密的金鑰,傳輸給對方,然後雙方使用對稱性加密演算法傳輸資料。

需要注意的是,類似 Diffie-Hellman 演算法,非對稱加密演算法也無法確定通訊雙方的身份,依然會遭到中間人攻擊。比如 Hack 攔截 Bob 發出的公鑰,然後冒充 Bob 的身份給 Alice 傳送自己的公鑰,那麼不知情的 Alice 就會把私密資料用 Hack 的公鑰加密,Hack 可以通過私鑰解密竊取。

那麼,Diffie-Hellman 演算法和 RSA 非對稱加密演算法都可以一定程度上解決金鑰配送的問題,也具有相同的缺陷,二者的應用場景有什麼區別呢?

簡單來說,根據兩種演算法的基本原理就可以看出來:

如果雙方有一個對稱加密方案,希望加密通訊,而且不能讓別人得到鑰匙,那麼可以使用 Diffie-Hellman 演算法交換金鑰。

如果你希望任何人都可以對資訊加密,而只有你能夠解密,那麼就使用 RSA 非對稱加密演算法,公佈公鑰。

下面,我們嘗試著解決認證傳送方身份的問題。

四、數字簽名

剛才說非對稱加密,把公鑰公開用於他人對資料加密然後發給你,只有用你手上對應的私鑰才能將密文解密。其實,私鑰也可用用來加密資料的,對於 RSA 演算法,私鑰加密的資料只有公鑰才能解開

數字簽名也是利用了非對稱性金鑰的特性,但是和公鑰加密完全顛倒過來:仍然公佈公鑰,但是用你的私鑰加密資料,然後把加密的資料公佈出去,這就是數字簽名

你可能問,這有什麼用,公鑰可以解開私鑰加密,我還加密發出去,不是多此一舉嗎?

是的,但是數字簽名的作用本來就不是保證資料的機密性,而是證明你的身份,證明這些資料確實是由你本人發出的。

你想想,你的私鑰加密的資料,只有你的公鑰才能解開,那麼如果一份加密資料能夠被你的公鑰解開,不就說明這份資料是你(私鑰持有者)本人釋出的嗎?

當然,加密資料僅僅是一個簽名,簽名應該和資料一同發出,具體流程應該是:

1、Bob 生成公鑰和私鑰,然後把公鑰公佈出去,私鑰自己保留。

2、用私鑰加密資料作為簽名,然後將資料附帶著簽名一同釋出出去

3、Alice 收到資料和簽名,需要檢查此份資料是否是 Bob 所發出,於是用 Bob 之前發出的公鑰嘗試解密簽名,將收到的資料和簽名解密後的結果作對比,如果完全相同,說明資料沒被篡改,且確實由 Bob 發出。

為什麼 Alice 這麼肯定呢,畢竟資料和簽名是兩部分,都可以被掉包呀?原因如下:

1、如果有人修改了資料,那麼 Alice 解密簽名之後,對比發現二者不一致,察覺出異常。

2、如果有人替換了簽名,那麼 Alice 用 Bob 的公鑰只能解出一串亂碼,顯然和資料不一致。

3、也許有人企圖修改資料,然後將修改之後的資料製成簽名,使得 Alice 的對比無法發現不一致;但是一旦解開簽名,就不可能再重新生成 Bob 的簽名了,因為沒有 Bob 的私鑰。

綜上,數字簽名可以一定程度上認證資料的來源。之所以說是一定程度上,是因為這種方式依然可能受到中間人攻擊。一旦涉及公鑰的釋出,接收方就可能收到中間人的假公鑰,進行錯誤的認證,這個問題始終避免不了。

說來可笑,數字簽名就是驗證對方身份的一種方式,但是前提是對方的身份必須是真的... 這似乎陷入一個先有雞還是先有蛋的死迴圈,要想確定對方的身份,必須有一個信任的源頭,否則的話,再多的流程也只是在轉移問題,而不是真正解決問題

五、公鑰證書

證書其實就是公鑰 + 簽名,由第三方認證機構頒發。引入可信任的第三方,是終結信任迴圈的一種可行方案。

證書認證的流程大致如下:

1、Bob 去可信任的認證機構證實本人真實身份,並提供自己的公鑰。

2、Alice 想跟 Bob 通訊,首先向認證機構請求 Bob 的公鑰,認證機構會把一張證書(Bob 的公鑰以及自己對其公鑰的簽名)傳送給 Alice。

3、Alice 檢查簽名,確定該公鑰確實由這家認證機構傳送,中途未被篡改。

4、Alice 通過這個公鑰加密資料,開始和 Bob 通訊。

PS:以上只是為了說明,證書只需要安裝一次,並不需要每次都向認證機構請求;一般是伺服器直接給客戶端傳送證書,而不是認證機構。

也許有人問,Alice 要想通過數字簽名確定證書的有效性,前提是要有該機構的(認證)公鑰,這不是又回到剛才的死迴圈了嗎?

我們安裝的正規瀏覽器中都預存了正規認證機構的證書(包含其公鑰),用於確認機構身份,所以說證書的認證是可信的。

Bob 向機構提供公鑰的過程中,需要提供很多個人資訊進行身份驗證,比較嚴格,所以說也算是可靠的。

獲得了 Bob 的可信公鑰,Alice 和 Bob 之間的通訊基於加密演算法的保護,是完全無懈可擊的。

現在的正規網站,大都使用 HTTPS 協議,就是在 HTTP 協議和 TCP 協議之間加了一個 SSL/TLS 安全層。在你的瀏覽器和網站伺服器完成 TCP 握手後,SSL 協議層也會進行 SSL 握手交換安全引數,其中就包含該網站的證書,以便瀏覽器驗證站點身份。SSL 安全層驗證完成之後,上層的 HTTP 協議內容都會被加密,保證資料的安全傳輸。

這樣一來,傳統的中間人攻擊就幾乎沒有了生存空間,攻擊手段只能由技術缺陷轉變為坑蒙拐騙。事實上,這種手段的效果反而更高效,比如我就發現網上不少下載網站釋出的瀏覽器,不僅包含亂七八糟的導航和收藏網址,還包含一些不正規的認證機構證書。任何人都可以申請證書,這些不正規證書很可能造成安全隱患

六、最後總結

對稱性加密演算法使用同一個金鑰加密和解密,難以破解,加密速度較快,但是存在金鑰配送問題。

Diffie-Hellman 金鑰交換演算法可以讓雙方「心有靈犀一點通」,一定程度解決金鑰配送問題,但是無法驗證通訊方的身份,所以可能受到中間人攻擊。

非對稱性加密演算法生成一對兒金鑰,把加密和解密的工作分開了。

RSA 演算法作為經典的非對稱加密演算法,有兩種用途:如果用於加密,可以把公鑰釋出出去用於加密,只有自己的私鑰可以解密,保證了資料的機密性;如果用於數字簽名,把公鑰釋出出去後,用私鑰加密資料作為簽名,以證明該資料由私鑰持有者所傳送。但是無論那種用法,涉及公鑰的釋出,都無法避免中間人攻擊。

公鑰證書就是公鑰 + 簽名,由可信任的第三方認證機構頒發。由於正規瀏覽器都預裝了可信的認證機構的公鑰,所以可以有效防止中間人攻擊。

HTTPS 協議中的 SSL/TLS 安全層會組合使用以上幾種加密方式,所以說不要安裝非正規的瀏覽器,不要亂安裝未知來源的證書

密碼技術只是安全的一小部分,即便是通過正規機構認證的 HTTPS 站點,也不意味著可信任,只能說明其資料傳輸是安全的。技術永遠不可能真正保護你,最重要的還是得提高個人的安全防範意識,多留心眼兒,謹慎處理敏感資料。

_____________

我的 線上電子書 有 100 篇原創文章,手把手帶刷 200 道力扣題目,建議收藏!對應的 GitHub 演算法倉庫 已經獲得了 70k star,歡迎標星!

test ad