本節內容
- 網絡數據傳輸安全概述
- 數據加密算法分類
- SSH工作原理
- HTTPS工作原理
- 參考資料
個人一直在努力推動git在公司內部的普及和使用,前些日子在公司內部做了一次分享課,給大家介紹了下項目發布流程相關的內容,順便普及了一些git的相關知識。對git是什么,以及怎樣配置和使用它做了一些說明。但事后,很多同事的反饋,讓我意識到他們很多人都卡在ssh免密鑰登錄的配置上。我們常說,學習一個新的東西應該遵循3W1H法則--WAHT(是什么),WHEN(什么時候用),HOW(怎樣用)和 WHY(為什么這樣用)。我想大家應該是因為不知道為什么這樣用,所以才會感到困惑。剛好,最近也在整理“使用Python相關模塊進行數據加密”的文檔,需要做些理論性的鋪墊,所以才想寫這篇文章,希望對大家有所幫助。
另外需要說明的是,網絡安全涉及很多方面的很多內容,本文只是針對網絡數據傳輸過程中的安全性發表一下個人認識和看法。如果描述的有什么不妥之處,歡迎大家留言交流和指正。
一、網絡數據傳輸安全概述
我們說的數據加密與解密通常是為了保證數據在網絡傳輸過程中的安全性。在網絡發展初期,網絡的數據安全性是沒有被足夠的重視的。事實上,當時為了實現數據可以通過網絡進行傳輸已經耗費了科學家大部分男細胞,因此在TCP/IP協議設計的初期,他們也實在沒有太多精力去過多考慮數據在網絡傳輸過程中可能存在的安全性問題。隨著TCP/IP協議及相關技術的日漸成熟,網絡數據傳輸技術越來越穩定,人們才慢慢開始重視這個問題,美國國家標準與技術研究院(National Institue of Standard and Technology,簡稱NIST)也開始制定相關的安全標準。
網絡安全涉及到很多個方面,我們這里僅僅討論下網絡數據傳輸過程中可能受到的威脅,其中常見的有:
- 數據竊聽
- 數據篡改
- 身份偽裝
針對以上威脅,我們介紹下網絡數據傳輸的安全性涉及的幾個方面:
1. 機密性
機密性是指對要傳輸的數據進行加密和解密,防止第三方看到通信數據的明文內容。其對應的通信過程如下:
數據發送方:
plaintext(明文) ==> 轉換算法 ==> ciphertext(密文)
數據接收方:
ciphertext(密文) ==> 轉換算法 ==> plaintext(明文)
2. 完整性
數據完整性是指不允許數據在傳輸過程中被修改(第三方惡意篡改或電平信號造成的部分數據丟失),但是它不要求數據的機密性,也就是說允許其他人看到明文數據。我們通常通過以不可逆的算法對數據提取特征碼(也叫數據指紋),通過驗證特征碼的一致性來判斷數據是否被修改過,通信過程如下:
數據發送發:
plaintext(明文) ==> 轉換算法 ==> plaintext(明文) + footprint(數據指紋A)
數據接收方:
plaintext(明文) + footprint(數據指紋A) ==> 轉換算法 ==> footprint(數據指紋B) ==> 對比數據指紋A與B是否一致
3. 身份驗證
身份驗證通常是指數據接收方需要確認發送數據給自己的數據是自己想要通信的那一方,防止他人冒充通信對方的身份進行通信。身份驗證的大體原理是:數據發送方與數據接收方約定一種特殊的數據加解密方式,數據發送方將一個通過約定的加密方式進行加密后的數據發送給數據接收方,數據接收方如能按照約定的加密方式正確解密該數據就表示對數據發送方的身份驗證成功。其對應的通信過程如下:
數據發送方:
plaintext(明文) ==> 轉換算法 ==> ciphertext(密文)
數據接收方:
ciphertext(密文) ==> 轉換算法 ==> plaintext(明文)
二、數據加密算法分類
上面提到的網絡數據傳輸所涉及到的幾個方面都需要特定的轉換算法來實現,常用的轉換算法(數據加密/解密算法)大體上可以分為以下幾類:
1. 對稱加密
對稱加密是指數據加密與解密使用相同的密鑰。
主要功能:
通常用于保證數據的機密性。
常用的算法實現:
- DES: Data Encryption Standard,秘鑰長度為56位,2003年左右被破解--秘鑰可以暴力破解。
- 3DES: DES的改進版本。
- AES: Advanced Encryption Standard,支持的秘鑰長度包括 128bits,192bits,258bits,384bits,512bits。
需要說明的是,秘鑰長度越長,數據加密與解密的時間就越久。
特點:
- 加密與解密使用的密鑰相同。
- 在一定程度上實現了數據的機密性,且簡單、快速。
- 但是由于算法一般都是公開的,因此機密性幾乎完全依賴于密鑰。
- 同一發送方與不同接收方進行通信時應使用不同的密鑰,防止數據被竊聽或攔截后被解密。
存在的問題:
- 當通信對象很多時會面臨眾多秘鑰的有效管理問題。
- 對于一個新的數據通信對象,密鑰怎樣進行傳輸的問題。
2. 單向加密
單向加密是指只能對明文數據進行加密,而不能解密數據。
主要功能:
通常用于保證數據的完整性。
常用的算法實現:
- MD5: 128bits
- SHA: SHA1(160bits), SHA224, SHA256, SHA384
特點:
- 不可逆:無法根據數據指紋/特征碼還原原來的數據。
- 輸入相同,輸出必然相同。
- 雪崩效應:輸入的微小改變,將會引起結果的巨大改變。
- 定長輸出:無論原始數據有多長,結果的長度是相同的。
存在的問題:
可能出現中間人攻擊,中間人可以對原始內容進行修改之后重新生成數據指紋,數據接收方驗證數據指紋時會發現數據是正常的。此時,數據發送方只能把生成的數據指紋進行加密后再發送給數據接收方,那么問題就又回到了加密密鑰的傳輸和管理上。
3. 公鑰加密(也叫非對稱加密)
公鑰加密,也被稱作非對稱加密,也就是說加密和解密所使用的密鑰是不同的。
主要作用:
通常用于保證身份驗證。
常用的公鑰加密算法有:
- RSA: 可以實現數字簽名 和 數據加密
- DSA: 只能實現數字簽名,不能實現數據加密
特點:
- 加密與解密使用的不同的密鑰。
- 實際上它所使用的密鑰是一對兒,一個交公鑰,一個叫私鑰。這對密鑰不是獨立的,公鑰是從私鑰中提煉出來,因此私鑰是很長的,968位、1024位、2048位、4096位的都有。
- 通常公鑰是公開的,所有人都可以得到;私鑰是不能公開的,只有自己才有。
- 用公鑰機密的內容只能用與之對應的私鑰才能解密,反之亦然,這個特點尤為重要。
我們發現公鑰加密“貌似”已經解決了密鑰管理的問題--所有人只需要知道自己的那一對兒密鑰即可,需要跟誰通信就去獲取對方的公鑰,然后通過這個公鑰對數據進行加密和機密就可以了。我們可以用它來完成以下兩件事情:
- 用自己的私鑰加密, 可以保證身份驗證,因為用你的私鑰加密的數據只能用你的公開的公鑰才能解密數據;但是不能保證數據的機密性,因為所有人都知道你的公鑰。瀏覽器檢查CA證書合法性時,驗證CA機構的數字簽名時就是通過這種方式進行的。
- 用對方的公鑰加密, 可以保證數據的機密性,因為只有用對方的私鑰才能解密,而對方的私鑰只有他一個人有。HTTPS通信時,通過密鑰協商技術得到的密鑰進行傳輸時就是通過這種方式來保證機密性的。其實用對方公鑰加密也可以用于用于身份驗證,驗證過程是:A用B的公鑰加密數據后將密文傳輸給B,B用自己的私鑰進行解密并將明文發送回給A,A對比B返回的明文和自己加密前的明文一致則表示對B完成了身份驗證,通過SSH進行免密鑰登錄時就是通過這種方式來完成用戶身份驗證的。
事實上,公鑰加密算法很少用于數據加密,它通常只是用來做身份認證,因為它的密鑰太長,加密速度太慢--公鑰加密算法的速度甚至比對稱加密算法的速度慢上3個數量級(1000倍)。
存在的問題:
- 既然公鑰加密通常只用于身份驗證,而不是用于保證數據的機密性,也就意味著這個密鑰對兒并不能完全作為加密和解密數據的秘鑰來用。那么,秘鑰的管理和傳輸問題依然存在著,這個問題到底怎樣來解決呢?
- 另外還有個問題就是,如果有人偽造了一對兒密鑰,把其中的公鑰發送給別人怎么辦?怎樣驗證以獲取公鑰的合法性呢?
密鑰管理的解決方案:
實際上,已經存在一種專門用于秘鑰交換的算法--Diffie-Hellman加密算法。該加密算法本身僅限于秘鑰的交換用途,被許多商用產品用作秘鑰交換技術。這種秘鑰交換技術的目的在于使得兩個用戶安全的交換一個密鑰,以便用于之后的數據對稱加密。也就是說,通信雙方可以通過這個技術,動態的協商生成一個用于對稱加密的密鑰,而不用管理很多靜態的密鑰,這樣就解決了密鑰的管理問題。
需要說明的是,在通過秘鑰交互技術動態協商生成密鑰之前,通常需要先通過公鑰加密算法對對方的身份進行驗證。實際上,https就是這樣工作的。
防止公鑰被偽造的解決方案
公鑰實際上也是一段文本,驗證公鑰的合法性涉及到兩個方面:
- 1)該公鑰的發布者身份是否合法
- 2)該公鑰的內容是否被篡改過
其實,這個已經不是靠純技術能解決的問題了,這需要借助一些機構和人為約定來解決。常見的解決方案有兩種:
- 1)公鑰的合法擁有者,通過官方渠道聲明其密鑰的數據指紋: 既然時官方發布的信息,那么身份的合法性是有保證的;用戶在獲取公鑰后也生成一個數據指紋,通過對比這兩個數據指紋就知道公鑰內容是否被修改過;SSH的身份驗證實際上就是這個原理。
- 2)通過一些權威的機構來完成這些驗證: 比如https使用的證書就是由CA機構簽發的,這個在后面講https原理時再做具體介紹。
我們常見的對于上面這些加密算法的經典應用就是ssh和https了,它們都是使用這些加密算法實現的網絡協議。下面我們對ssh和https的工作原理進行下介紹,一方面當做上面這些加密算法的實例講解,幫助大家了解這些算法的經典應用;另一方面,也幫助大家更深入的理解ssh和https是什么,以及它們是怎樣工作的。
三、SSH工作原理
1. SSH是什么?
簡單來說,SSH就是一種網絡協議,主要用于計算機之間的加密登錄與數據傳輸,使用方式如下:
# ssh user@host
表示要以user這個用戶的身份登錄host這臺網絡機器。也可以省略前面的user,這樣來用ssh host
,表示以當前本地登錄的用戶名登錄host這臺網絡機器。
早期,人們主要是通過telnet協議進行計算機之間的登錄操作,但是它有一個很嚴重的安全隱患就是“數據是明文傳輸的”,登錄時傳輸的包括用戶名和密碼在內的所有信息都有可能會被惡意攔截而暴露。而SSH則是將登錄信息全部加密后進行傳輸的,因此使用SSH進行登錄時安全的,即使數據在傳輸過程中被截獲,里面的密碼已經被加密而不會泄露。
現在SSH作為互聯網安全的一個基本解決方案,已經在全世界獲得推廣,且目前已經成為Linux系統的標準配置。需要說明的是,SSH只是一種協議,它有多種軟件實現,既有商業的,也有開源的。OpenSSH是當前使用最為廣泛的一個SSH協議的開源實現。
2. SSH工作原理
其實SSH是充分利用了公鑰加密/非對稱機密 、對稱加密 和 單向加密 來實現數據安全登錄的。在使用SSH進行通信時,通信過程分為以下幾個步驟:
- 1)生成會話密鑰: 這個會話密鑰,不是密鑰對兒中公鑰或私鑰,而是通過密鑰協商技術生成密鑰。這個密鑰會被通過被登錄機器的密鑰對進行加密后傳輸,用于后續所有(通過對稱加密方式進行的)加密通信。
- 2)用戶身份認證(登錄):* 這個對登錄者進行身份驗證的過程是通過登錄者的密鑰對兒對數據進行加解密驗證實現的,這個過程中傳輸的所有數據都是通過上一步生成的密鑰加密過的。
- 3)數據加密通信: 后面就行基于第1步生成的密鑰進行數據加密傳輸的通信過程了。
下面來看具體解析。
賬號密碼安全登錄的實現
上面提到,SSH是通過對數據進行加密后進行傳輸來保證數據安全的。但是,SSH的數據加密采用的是對稱加密算法,只是對稱加密所使用的密鑰是通過公鑰加密/非對稱加密實現加密后的安全傳輸的。另外,每臺Linux機器都有自己的密鑰對兒(通常放在/etc/ssh目錄下),這個密鑰對兒跟具體的用戶無關。其工作流程是:
- 1)在主機A上向主機B發送連接請求;
- 2)主機B在與用戶建立連接后,把自己的公鑰發送給主機A;
- 3)主機A通過密鑰協商技術產生一個隨機密鑰,然后使用主機B的公鑰對這個隨機密鑰進行加密后發送給主機B;
- 4) 主機B接收到主機A發送過來的密文形式的密鑰后,通過自己的私鑰進行解密,得到對稱加密使用的密鑰明文;至此,會話密鑰已經生成完畢了;
- 5)主機A通過生成的會話密鑰對賬號和密碼等信息進行加密然后發送給主機B;
- 6)主機B接收到加密信息后,使用會話密鑰進行解密,從而得到明文的賬號和密碼進行賬號驗證;
- 7)主機B在驗證賬號和密碼后通知主機A是否登錄成功;
這樣即便有人結果了賬號密碼信息,也是密文信息,并不能知道里面是什么內容。貌似已經OK了,但是,主機A怎么驗證主機B的身份呢?如果有主機C冒充主機B截獲了登錄請求,將自己偽造的公鑰發送給主機A,怎么辦?盡管信息是加密過的,通信過程也是合法的,但是通信信息都被主機C截獲了,其實這就是所謂的“中間人攻擊”(Man-in-the-middle attack)。其實,對主機B進行驗證就是對主機B發送過來的公鑰的合法性進行驗證的過程。
公鑰合法性驗證的實現
上面我們提到過,驗證公鑰的合法性有兩種方式:
- 1)驗證公鑰的官方發布的公鑰數據指紋
- 2)通過權威的結構進行驗證
SSH主要用于機器之間的安全登錄,因此通常不會通過權威的機構去簽發證書,它主要是通過驗證數據指紋的方式來驗證公鑰的合法性的。公鑰的合法性驗證是發生在主機A接收到主機B發送的公鑰之后,主機A向主機B協商產生會話密鑰之前,也就是上個部分所列舉的數據機密時間的第2個步驟和第3個步驟之間。具體的工作流程如下:
- 1)上個部分所列舉的數據加密實現的第1-2步;
- 2)主機A會去當前用戶家目錄下的.ssh/known_hosts文件中查找是否存在該機器的公鑰,如果不存在,表示主機A是第一次與該主機進行通信,那么主機A會計算出該公鑰的數據指紋并要求用戶對該指紋進行合法性確認。就是我們經常看到的的這樣子:
- 3)用戶需要把目標主機管理員公布的公鑰的數據指紋與主機A計算得到的數據指紋進行比對,如果一致,則說明該公鑰是合法的;如果不一致則說明不合法;
- 4)用戶如果確認該公鑰是合法的,則輸入yes表示繼續后面的連接,主機A則會把這個公鑰的內容保存到當前用戶家目錄下的.ssh/known_hosts文件中,然后提示用戶輸入密碼,如下圖所示:
下次再登錄,執行到步驟2時,主機A發現該公鑰已經在.ssh/known_hosts文件中存在了,就不用要求再次確認了,而是會直接提示輸出密碼:
- 5)至此,主機B的身份合法性驗證就結束了。
每個用戶都有自己的kown_hosts文件,它們是相互獨立的。我們也可以為所有用戶保存一份公共的可信賴的遠程主機的公鑰,這個文件通常是/etc/ssh/ssh_known_hosts。
問題:假如之前我們通過ssh登錄過的一臺機器的IP被綁定到其他機器上了會出現什么情況?
當機器A接收到機器B的公鑰指紋時,發現knowns_hosts文件中雖然有機器B的公鑰,但是計算得出的公鑰指紋與機器B發送過來的公鑰指紋不一致。這肯定是不一致的,因為每臺機器的密鑰對都是隨機生成的,幾乎不可能出現重復。因此,我們會看到如下提示信息:
上面的大概意思是,主機A發現主機B的公鑰指紋對不上了,懷疑我們正在遭受中間人攻擊(即有人在冒充主機B),并且密碼驗證方式和鍵盤交互驗證方式都被禁止使用了。其實,我們自己知道是因為IP被綁定到其他機器上引起的這個問題,所以我們如果想繼續登錄新的主機B,只需要在.ssh/known_hosts文件中把原來保存的主機B的公鑰刪掉就可以了。
3. SSH免密鑰登錄的實現
使用SSH免密鑰登錄的優點
大家都知道,SSH免密鑰登錄是通過公鑰認證的,用戶登錄時只需要提供用戶名,而不需要輸入密碼。其實其優點不止這一個,我們來總結下:
- 1)使用賬號和密碼進行登錄時,由于用戶無法設置空密碼,因此每次登錄都要輸入密碼。而且即使系統允許給用戶設置空密碼,也是十分危險的行為。而公鑰認證允許用戶給私鑰設置空密碼,同時還能保證安全性。
- 2)使用賬號和密碼進行登錄時密碼容易被人看到,且密碼也容易被猜到;而公鑰認證所使用的密鑰不用手動輸入,而且內容很長,因此安全性比較高。
- 3)使用賬號和密碼進行登錄時,服務器上的一個賬號如果想給多個人同時使用,機器密碼維護工作會變得很繁瑣,因為他們所有人都需要知道密碼是什么,當修改密碼也要通知他們每個人。而使用公鑰認證只需要把它們的公鑰保存在服務器上,如果要取消某個人的操作權限,只需要把這個人的公鑰刪掉,而不需要修改服務器密碼。
SSH免密鑰登錄過程
其實登錄的過程就是被登錄端對登錄用戶進行“身份驗證”的過程,前面是通過賬號和密碼來驗證用戶身份,因為密碼應該只有該賬號的擁有者才知道。而我們知道公鑰加密算法中,用公鑰加密的數據只能由與其配對的私鑰才能解密,而私鑰只有用戶自己才有。那么,我們是否可以通過這種方式來驗證用戶身份呢?實際上SSH免密鑰登錄就是這樣的原理。比如,我們想在主機A上以root用戶以SSH免密鑰的方式登錄主機B,登錄驗證過程是這樣的:
- 1)主機A與主機B協商產生會話密鑰;
- 2)主機A會向主機B發送一個登錄請求(如:
root@192.168.1.2
),發送的信息包括用戶名root和root的公鑰指紋,且所有信息都是通過會話密鑰加密過的。 - 3)主機B通過會話密鑰解密主機A發送的數據得到請求登錄的用戶名root和root的公鑰指紋,然后讀取root用戶家目錄下的所有公鑰數據(/root/.ssh/autorized_keys文件中),并分別通過單向加密算法獲取各公鑰的數據指紋與主機A發送過來的數據指紋做對比,從而找到主機A上的root用戶的公鑰;
- 4)主機B使用找到的root用戶的公鑰對一個隨機數進行加密發送發送給主機A;
- 5)主機A使用root用戶的私鑰對主機B發送的隨機數密文進行解密,然后把解密結果發送給主機B;
- 6)主機B驗證主機A解密后的數據與自己發送的數據一致,則對root用戶的身份驗證成功;
那么主機A是怎樣獲取root用戶的私鑰的呢?主機B又是怎樣獲取root用戶的公鑰的呢? 這個就是實現SSH免密鑰登錄所要配置的內容:
- 1)生成密鑰對兒:在當前機器A上,可以通過
ssh-keygen
命令生成一個ssh密鑰對兒,一路回車就可以;生成的密鑰對兒默認保存在當前登錄用戶家目錄下的.ssh目錄,也可以指定保存目錄。我們當前是以root用戶登錄,因此是保存在/root/.ssh目錄:
- 2)我們可以把這個密鑰對兒中的兩個文件復制到其他用戶家目錄的.ssh目錄下(如/home/wader/.ssh/目錄),也可以復制到其他任意目錄。需要說明的是一定要注意目錄和文件的權限:.ssh 目錄的權限必須是0700,authorized_keys 文件權限必須是0600。
- 3)當在主機A上通過
ssh root@hostB
進行登錄時,主機A會嘗試讀取登錄用戶的家目錄下的私鑰文件(這里是以root用戶登錄主機B,因此主機A會讀取/root/.ssh/id_rsa文件作為私鑰),也可以通過-i選項指定要使用的私鑰文件; - 4)我們需要手動把公鑰的內容復制到要登錄機器B的相應用戶(如root)家目錄下的指定文件中:/home/root/.ssh/autorized_keys;可以使用
ssh-copy-id root@hostB
命令直接完成這個操作,也可以通過復制粘貼的方式來完成; - 5)在當前機器上就可以通過ssh私鑰使用root用戶登錄機器B了。
4. ssh免密鑰登錄在git中的使用
我們在管理git倉庫中的項目時,可以使用http/https協議,也可以使用ssh協議來管理我們的項目代碼:
http/https協議:
http://192.168.1.1/GROUP_OR_USER/PROJECT_NAME.git
https://192.168.1.1/GROUP_OR_USER/PROJECT_NAME.git
ssh協議:
ssh://git@192.168.1.1/GROUP_OR_USER/PROJECT_NAME.git
無論使用http/https協議還是ssh協議來管理項目倉庫,對于非公開的倉庫都是需要進行登錄(即賬戶身份驗證)的。如果我們使用http/https協議的話,就需要提供用戶名和密碼進行驗證;如果我們使用ssh協議的話,就可以把我們公鑰保存到項目倉庫機器的指定位置,來通過非對稱加密的方式進行身份驗證,驗證的原理上面已經詳細說明過了。
四、HTTPS工作原理
HTTPS實際上就是HTTP協議和SSL/TSL協議的組合,可以把HTTPS大致理解為“HTTP over SSL”或“HTTP over TSL”。關于它們的相關介紹,可以參考這篇文章。對于HTTPS我們應該有以下幾個認知:
- 1)使用HTTPS傳輸數據是安全的,因為數據都是被加密傳輸的;
- 2)使用HTTPS需要在服務器端配置密鑰對;
- 3)使用HTTPS需要花錢找專業的權威機構進行CA證書的簽發。
那么使用HTTPS與網站服務器進行交互的流程和原理到底是怎樣的呢?讓我們先以逆向思考的方式來進行說明:
我們說過,公鑰加密/非對稱加密方式雖然安全,但是由于密鑰過長,加密和解密速度都遠遠低于對稱加密。因此,出于對性能方面的考慮,HTTPS并不是把所有傳輸的數據都使用公鑰加密的方式進行機密性的保護,而是繼續使用對稱加密的方式來加密數據。還有一個原因就是,使用公鑰機密算法來保證數據機密性的話,需要通信雙方都要有密鑰對兒,否則總有一方發出的數據是能被對方公布的公鑰解密的。
既然時使用對稱加密的方式加密數據,就需要有一個通信雙方都知道的加解密所使用的密鑰。HTTPS是通過上面提到的密鑰交換技術來動態協商這個密鑰的,實際上就是由客戶端生成一個隨機密鑰,然后發送給服務器端,這樣就解決了密鑰的管理問題。
既然說HTTPS是安全的,那么客戶端生成的這個隨機密鑰肯定不能以明文的方式發送給服務器端啊。是的,當客戶端以https的方式訪問一個站點時,該站點會自動下發其公鑰信息。客戶端會使用這個公鑰對產生的隨機密鑰進行加密,然后傳送給服務器端。服務器端以自己的私鑰對這個密文進行解密,然后得到這個密鑰的明文內容。至此,客戶端與服務端用于對稱加密和解密的密鑰協商與傳輸工作已經安全的完成了。
那么要通過網絡獲取服務器端的公鑰信息,那么怎么驗證該公鑰信息的合法性呢?我們上面說過,不是所有問題都能依賴技術來解決的。這里要驗證公鑰信息的合法性就要依靠CA證書簽發機構了,網站服務的提供者必須找一個大家都信任的機構來對他提供的公鑰進行簽名,用戶得到一個網站下發的公鑰后看到有這個機構的簽名就認為這個公鑰是合法的,是可信賴的。
那么CA機構的簽名要以什么樣的形式來提供呢?實際上網站服務器下發給客戶端(通常是瀏覽器)的公鑰已經不僅僅是密鑰對兒中公鑰的內容了,而是包含了證書簽發機構寫入的其他信息的CA證書。這個CA證書中包括證書簽發機構的標識和公鑰的數據指紋,當然還有包含網站服務提供者的公鑰信息以及證書到期時間等等。但是,我們前面提到過,單向加密只能保證數據的完整性,不能保證數據機密性。CA證書的偽造者完全可以偽造公鑰信息并生成相應的數據指紋,然后發送給用戶。那么現在的問題就變成了要驗證CA證書中公鑰的合法性以及CA證書提供者的身份了。貌似問題只是轉移了,而沒有被解決。
其實每個CA證書的簽發機構也都有自己的密鑰對兒,他們放在CA證書中的公鑰的數據指紋時通過自己的私鑰加密過的,而這些CA證書簽發機構的公鑰是被各瀏覽器廠商內置在瀏覽器內部的。當瀏覽器接收到某網站服務器下發的CA證書后會根據CA證書中簽發機構的標識來讀取瀏覽器內置的相應CA簽發機構的公鑰信息,通過這個公鑰信息對公鑰數據指紋的密文進行解密就可以得到CA證書中包含的公鑰信息的真實數據指紋。瀏覽器再通過單向加密的方式自己計算一次CA證書中包含的公鑰信息的數據指紋,兩個數據指紋一致則說明這個CA證書確實是該CA機構簽發的,同時也證明了CA證書中的公鑰信息沒有被篡改過。至此,所有的問題就都解決了。
現在我們再來以正常的順序描述一下使用HTTPS與網站服務器進行交互的過程:
- 1)瀏覽器A與網站服務器B通過三次握手后建立網絡連接。
- 2)瀏覽器A告訴網站服務器B:我想跟你通過HTTPS協議進行秘密交流。
- 3)網站服務器B把包含自己公鑰信息的CA證書下發給瀏覽器A,并告訴瀏覽器A這個CA證書里有我的公鑰信息,你決定一個對稱加密使用的秘鑰串,然后通過這個公鑰加密后發送給我。
- 4) 瀏覽器A接收到網站服務器B下發的CA證書后,對這個CA證書的及其包含的公鑰信息的合法性表示懷疑。于是根據CA證書中包含的證書簽發機構的標識找到自身內置的該簽發機構的公鑰對CA證書中公鑰的數據指紋進行解密,然后再自己計算一下CA證書中公鑰的數據指紋,對了一下這兩個數據指紋是一致的。瀏覽器A放心了,知道這個CA證書是合法的,CA證書中的公鑰也沒有被篡改過。
- 5)然后瀏覽器A通過通過密鑰協商技術產生了一個隨機的字符串作為與網站服務器B進行秘密通信的密鑰,并把這個密鑰通過CA證書中包含的公鑰進行加密后發送給網站服務器B。
- 6)網站服務器B接收到密文格式的密鑰后,通過自己的私鑰進行解密得到密鑰的明文內容。
- 7)瀏覽器A和網站服務器B開始了秘密交流。
五、參考資料
文章列表