若是發現文中有錯誤的地方,或者有什麼地方說得不夠清楚,歡迎指出!html
一、基礎知識算法
這部份內容主要解釋一些概念和術語,最好是先理解這部份內容。安全
1.一、公鑰密碼體制(public-key cryptography)bash
公鑰密碼體制分爲三個部分,公鑰、私鑰、加密解密算法,它的加密解密過程以下:服務器
加密:經過加密算法和公鑰對內容(或者說明文)進行加密,獲得密文。加密過程須要用到公鑰。 解密:經過解密算法和私鑰對密文進行解密,獲得明文。解密過程須要用到解密算法和私鑰。注意,由公鑰加密的內容,只能由私鑰進行解密,也就是說,由公鑰加密的內容,若是不知道私鑰,是沒法解密的。 公鑰密碼體制的公鑰和算法都是公開的(這是爲何叫公鑰密碼體制的緣由),私鑰是保密的。你們都以使用公鑰進行加密,可是隻有私鑰的持有者才能解密。在實際的使用中,有須要的人會生成一對公鑰和私鑰,把公鑰發佈出去給別人使用,本身保留私鑰。網絡
1.二、對稱加密算法(symmetric key algorithms)字體
在對稱加密算法中,加密使用的密鑰和解密使用的密鑰是相同的。也就是說,加密和解密都是使用的同一個密鑰。所以對稱加密算法要保證安全性的話,密鑰要作好保密,只能讓使用的人知道,不能對外公開。這個和上面的公鑰密碼體制有所不一樣,公鑰密碼體制中加密是用公鑰,解密使用私鑰,而對稱加密算法中,加密和解密都是使用同一個密鑰,不區分公鑰和私鑰。加密
// 密鑰,通常就是一個字符串或數字,在加密或者解密時傳遞給加密/解密算法。前面在公鑰密碼體制中說到的公鑰、私鑰就是密鑰,公鑰是加密使用的密鑰,私鑰是解密使用的密鑰。spa
1.三、非對稱加密算法(asymmetric key algorithms)code
在非對稱加密算法中,加密使用的密鑰和解密使用的密鑰是不相同的。前面所說的公鑰密碼體制就是一種非對稱加密算法,他的公鑰和是私鑰是不能相同的,也就是說加密使用的密鑰和解密使用的密鑰不一樣,所以它是一個非對稱加密算法。
1.四、RSA簡介
RSA是一種公鑰密碼體制,如今使用得很普遍。若是對RSA自己有興趣的,後面看我有沒有時間寫個RSA的具體介紹。
RSA密碼體制是一種公鑰密碼體制,公鑰公開,私鑰保密,它的加密解密算法是公開的。 由公鑰加密的內容能夠而且只能由私鑰進行解密,而且由私鑰加密的內容能夠而且只能由公鑰進行解密。也就是說,RSA的這一對公鑰、私鑰均可以用來加密和解密,而且一方加密的內容能夠由而且只能由對方進行解密。
1.五、簽名和加密
咱們說加密,是指對某個內容加密,加密後的內容還能夠經過解密進行還原。 好比咱們把一封郵件進行加密,加密後的內容在網絡上進行傳輸,接收者在收到後,經過解密能夠還原郵件的真實內容。
這裏主要解釋一下簽名,簽名就是在信息的後面再加上一段內容,能夠證實信息沒有被修改過,怎麼樣能夠達到這個效果呢?通常是對信息作一個hash計算獲得一個hash值,注意,這個過程是不可逆的,也就是說沒法經過hash值得出原來的信息內容。在把信息發送出去時,把這個hash值加密後作爲一個簽名和信息一塊兒發出去。 接收方在收到信息後,會從新計算信息的hash值,並和信息所附帶的hash值(解密後)進行對比,若是一致,就說明信息的內容沒有被修改過,由於這裏hash計算能夠保證不一樣的內容必定會獲得不一樣的hash值,因此只要內容一被修改,根據信息內容計算的hash值就會變化。固然,不懷好意的人也能夠修改信息內容的同時也修改hash值,從而讓它們能夠相匹配,爲了防止這種狀況,hash值通常都會加密後(也就是簽名)再和信息一塊兒發送,以保證這個hash值不被修改。至於如何讓別人能夠解密這個簽名,這個過程涉及到數字證書等概念,咱們後面在說到數字證書時再詳細說明,這裏您先只需先理解簽名的這個概念。
二、一個加密通訊過程的演化
咱們來看一個例子,如今假設「服務器」和「客戶」要在網絡上通訊,而且他們打算使用RSA(參看前面的RSA簡介)來對通訊進行加密以保證談話內容的安全。因爲是使用RSA這種公鑰密碼體制,「服務器」須要對外發布公鑰(算法不須要公佈,RSA的算法你們都知道),本身留着私鑰。「客戶」經過某些途徑拿到了「服務器」發佈的公鑰,客戶並不知道私鑰。「客戶」具體是經過什麼途徑獲取公鑰的,咱們後面再來講明,下面看一下雙方如何進行保密的通訊:
2.1 第一回合:
「客戶」->「服務器」:你好
「服務器」->「客戶」:你好,我是服務器
「客戶」->「服務器」:????
由於消息是在網絡上傳輸的,有人能夠冒充本身是「服務器」來向客戶發送信息。例如上面的消息能夠被黑客截獲以下:
「客戶」->「服務器」:你好
「服務器」->「客戶」:你好,我是服務器
「客戶」->「黑客」:你好 // 黑客在「客戶」和「服務器」之間的某個路由器上截獲「客戶」發給服務器的信息,而後本身冒充「服務器」
「黑客」->「客戶」:你好,我是服務器
複製代碼
所以「客戶」在接到消息後,並不能確定這個消息就是由「服務器」發出的,某些「黑客」也能夠冒充「服務器」發出這個消息。如何肯定信息是由「服務器」發過來的呢?有一個解決方法,由於只有服務器有私鑰,因此若是隻要可以確認對方有私鑰,那麼對方就是「服務器」。所以通訊過程能夠改進爲以下:
2.2 第二回合:
「客戶」->「服務器」:你好
「服務器」->「客戶」:你好,我是服務器
「客戶」->「服務器」:向我證實你就是服務器
「服務器」->「客戶」:你好,我是服務器 {你好,我是服務器}[私鑰|RSA]
複製代碼
// 注意這裏約定一下,{} 表示RSA加密後的內容,[ | ]表示用什麼密鑰和算法進行加密,後面的示例中都用這種表示方式,例如上面的 {你好,我是服務器}[私鑰|RSA] 就表示用私鑰對「你好,我是服務器」進行加密後的結果。
複製代碼
爲了向「客戶」證實本身是「服務器」, 「服務器」把一個字符串用本身的私鑰加密,把明文和加密後的密文一塊兒發給「客戶」。對於這裏的例子來講,就是把字符串 「你好,我是服務器」和這個字符串用私鑰加密後的內容 {你好,我是服務器}[私鑰|RSA] 發給客戶。
「客戶」收到信息後,她用本身持有的公鑰解密密文,和明文進行對比,若是一致,說明信息的確是由服務器發過來的。也就是說「客戶」把 {你好,我是服務器}[私鑰|RSA] 這個內容用公鑰進行解密,而後和「你好,我是服務器」對比。由於由「服務器」用私鑰加密後的內容,由而且只能由公鑰進行解密,私鑰只有「服務器」持有,因此若是解密出來的內容是可以對得上的,那說明信息必定是從「服務器」發過來的。
假設「黑客」想冒充「服務器」:
「客戶」->「黑客」:向我證實你就是服務器
「黑客」->「客戶」:你好,我是服務器 {你好,我是服務器}[???|RSA] //這裏黑客沒法冒充,由於他不知道私鑰,沒法用私鑰加密某個字符串後發送給客戶去驗證。
「客戶」->「黑客」:????
複製代碼
因爲「黑客」沒有「服務器」的私鑰,所以它發送過去的內容,「客戶」是沒法經過服務器的公鑰解密的,所以能夠認定對方是個冒牌貨!
到這裏爲止,「客戶」就能夠確認「服務器」的身份了,能夠放心和「服務器」進行通訊,可是這裏有一個問題,通訊的內容在網絡上仍是沒法保密。爲何沒法保密呢?通訊過程不是能夠用公鑰、私鑰加密嗎?其實用RSA的私鑰和公鑰是不行的,咱們來具體分析下過程,看下面的演示:
2.3 第三回合:
「服務器」->「客戶」:你好,我是服務器
「客戶」->「服務器」:向我證實你就是服務器
「服務器」->「客戶」:你好,我是服務器 {你好,我是服務器}[私鑰|RSA]
「客戶」->「服務器」:{個人賬號是aaa,密碼是123,把個人餘額的信息發給我看看}[公鑰|RSA]
「服務器」->「客戶」:{你的餘額是100元}[私鑰|RSA]
複製代碼
注意上面的的信息 {你的餘額是100元}[私鑰],這個是「服務器」用私鑰加密後的內容,可是咱們以前說了,公鑰是發佈出去的,所以全部的人都知道公鑰,因此除了「客戶」,其它的人也能夠用公鑰對{你的餘額是100元}[私鑰]進行解密。因此若是「服務器」用私鑰加密發給「客戶」,這個信息是沒法保密的,由於只要有公鑰就能夠解密這內容。然而「服務器」也不能用公鑰對發送的內容進行加密,由於「客戶」沒有私鑰,發送個「客戶」也解密不了。
這樣問題就又來了,那又如何解決呢?在實際的應用過程,通常是經過引入對稱加密來解決這個問題,看下面的演示:
2.4 第四回合:
「服務器」->「客戶」:你好,我是服務器
「客戶」->「服務器」:向我證實你就是服務器
「服務器」->「客戶」:你好,我是服務器 {你好,我是服務器}[私鑰|RSA]
「客戶」->「服務器」:{咱們後面的通訊過程,用對稱加密來進行,這裏是對稱加密算法和密鑰}[公鑰|RSA] //藍色字體的部分是對稱加密的算法和密鑰的具體內容,客戶把它們發送給服務器。
「服務器」->「客戶」:{OK,收到!}[密鑰|對稱加密算法]
「客戶」->「服務器」:{個人賬號是aaa,密碼是123,把個人餘額的信息發給我看看}[密鑰|對稱加密算法]
「服務器」->「客戶」:{你的餘額是100元}[密鑰|對稱加密算法]
複製代碼
在上面的通訊過程當中,「客戶」在確認了「服務器」的身份後,「客戶」本身選擇一個對稱加密算法和一個密鑰,把這個對稱加密算法和密鑰一塊兒用公鑰加密後發送給「服務器」。注意,因爲對稱加密算法和密鑰是用公鑰加密的,就算這個加密後的內容被「黑客」截獲了,因爲沒有私鑰,「黑客」也無從知道對稱加密算法和密鑰的內容。
因爲是用公鑰加密的,只有私鑰可以解密,這樣就能夠保證只有服務器能夠知道對稱加密算法和密鑰,而其它人不可能知道(這個對稱加密算法和密鑰是「客戶」本身選擇的,因此「客戶」本身固然知道如何解密加密)。這樣「服務器」和「客戶」就能夠用對稱加密算法和密鑰來加密通訊的內容了。
總結一下,RSA加密算法在這個通訊過程當中所起到的做用主要有兩個:
由於私鑰只有「服務器」擁有,所以「客戶」能夠經過判斷對方是否有私鑰來判斷對方是不是「服務器」。 客戶端經過RSA的掩護,安全的和服務器商量好一個對稱加密算法和密鑰來保證後面通訊過程內容的安全。 若是這裏您理解了爲何不用RSA去加密通訊過程,而是要再肯定一個對稱加密算法來保證通訊過程的安全,那麼就說明前面的內容您已經理解了。(若是不清楚,再看下2.3和2.4,若是仍是不清楚,那應該是咱們說清楚,您能夠留言提問。)
到這裏,「客戶」就能夠確認「服務器」的身份,而且雙方的通訊內容能夠進行加密,其餘人就算截獲了通訊內容,也沒法解密。的確,好像通訊的過程是比較安全了。
可是這裏還留有一個問題,在最開始咱們就說過,「服務器」要對外發布公鑰,那「服務器」如何把公鑰發送給「客戶」呢?咱們第一反應可能會想到如下的兩個方法:
a)把公鑰放到互聯網的某個地方的一個下載地址,事先給「客戶」去下載。
b)每次和「客戶」開始通訊時,「服務器」把公鑰發給「客戶」。
可是這個兩個方法都有必定的問題,
對於a)方法,「客戶」沒法肯定這個下載地址是否是「服務器」發佈的,你憑什麼就相信這個地址下載的東西就是「服務器」發佈的而不是別人僞造的呢,萬一下載到一個假的怎麼辦?另外要全部的「客戶」都在通訊前事先去下載公鑰也很不現實。
對於b)方法,也有問題,由於任何人均可以本身生成一對公鑰和私鑰,他只要向「客戶」發送他本身的私鑰就能夠冒充「服務器」了。示意以下:
「客戶」->「黑客」:你好 //黑客截獲「客戶」發給「服務器」的消息
「黑客」->「客戶」:你好,我是服務器,這個是個人公鑰 //黑客本身生成一對公鑰和私鑰,把公鑰發給「客戶」,本身保留私鑰
「客戶」->「黑客」:向我證實你就是服務器
「黑客」->「客戶」:你好,我是服務器 {你好,我是服務器}[黑客本身的私鑰|RSA] //客戶收到「黑客」用私鑰加密的信息後,是能夠用「黑客」發給本身的公鑰解密的,從而會誤認爲「黑客」是「服務器」
複製代碼
所以「黑客」只須要本身生成一對公鑰和私鑰,而後把公鑰發送給「客戶」,本身保留私鑰,這樣因爲「客戶」能夠用黑客的公鑰解密黑客的私鑰加密的內容,「客戶」就會相信「黑客」是「服務器」,從而致使了安全問題。這裏問題的根源就在於,你們均可以生成公鑰、私鑰對,沒法確認公鑰對究竟是誰的。 若是可以肯定公鑰究竟是誰的,就不會有這個問題了。例如,若是收到「黑客」冒充「服務器」發過來的公鑰,通過某種檢查,若是可以發現這個公鑰不是「服務器」的就行了。
爲了解決這個問題,數字證書出現了,它能夠解決咱們上面的問題。先大概看下什麼是數字證書,一個證書包含下面的具體內容:
證書的有效期
公鑰
證書全部者(Subject)
簽名所使用的算法
指紋以及指紋算法
複製代碼
證書的內容的詳細解釋會在後面詳細解釋,這裏先只須要搞清楚一點,數字證書能夠保證數字證書裏的公鑰確實是這個證書的全部者(Subject)的,或者證書能夠用來確認對方的身份。也就是說,咱們拿到一個數字證書,咱們能夠判斷出這個數字證書究竟是誰的。至因而如何判斷的,後面會在詳細討論數字證書時詳細解釋。如今把前面的通訊過程使用數字證書修改成以下:
2.5 第五回合:
「客戶」->「服務器」:你好
「服務器」->「客戶」:你好,我是服務器,這裏是個人數字證書 //這裏用證書代替了公鑰
「客戶」->「服務器」:向我證實你就是服務器
「服務器」->「客戶」:你好,我是服務器 {你好,我是服務器}[私鑰|RSA]
複製代碼
注意,上面第二次通訊,「服務器」把本身的證書發給了「客戶」,而不是發送公鑰。「客戶」能夠根據證書校驗這個證書究竟是不是「服務器」的,也就是能校驗這個證書的全部者是否是「服務器」,從而確認這個證書中的公鑰的確是「服務器」的。後面的過程和之前是同樣,「客戶」讓「服務器」證實本身的身份,「服務器」用私鑰加密一段內容連同明文一塊兒發給「客戶」,「客戶」把加密內容用數字證書中的公鑰解密後和明文對比,若是一致,那麼對方就確實是「服務器」,而後雙方協商一個對稱加密來保證通訊過程的安全。到這裏,整個過程就完整了,咱們回顧一下:
2.6 完整過程:
step1: 「客戶」向服務端發送一個通訊請求
「客戶」->「服務器」:你好
step2: 「服務器」向客戶發送本身的數字證書。證書中有一個公鑰用來加密信息,私鑰由「服務器」持有
「服務器」->「客戶」:你好,我是服務器,這裏是個人數字證書
step3: 「客戶」收到「服務器」的證書後,它會去驗證這個數字證書究竟是不是「服務器」的,數字證書有沒有什麼問題,數字證書若是檢查沒有問題,就說明數字證書中的公鑰確實是「服務器」的。檢查數字證書後,「客戶」會發送一個隨機的字符串給「服務器」用私鑰去加密,服務器把加密的結果返回給「客戶」,「客戶」用公鑰解密這個返回結果,若是解密結果與以前生成的隨機字符串一致,那說明對方確實是私鑰的持有者,或者說對方確實是「服務器」。
「客戶」->「服務器」:向我證實你就是服務器,這是一個隨機字符串 //前面的例子中爲了方便解釋,用的是「你好」等內容,實際狀況下通常是隨機生成的一個字符串。
「服務器」->「客戶」:{一個隨機字符串}[私鑰|RSA]
step4: 驗證「服務器」的身份後,「客戶」生成一個對稱加密算法和密鑰,用於後面的通訊的加密和解密。這個對稱加密算法和密鑰,「客戶」會用公鑰加密後發送給「服務器」,別人截獲了也沒用,由於只有「服務器」手中有能夠解密的私鑰。這樣,後面「服務器」和「客戶」就均可以用對稱加密算法來加密和解密通訊內容了。
「服務器」->「客戶」:{OK,已經收到你發來的對稱加密算法和密鑰!有什麼能夠幫到你的?}[密鑰|對稱加密算法]
「客戶」->「服務器」:{個人賬號是aaa,密碼是123,把個人餘額的信息發給我看看}[密鑰|對稱加密算法]
「服務器」->「客戶」:{你好,你的餘額是100元}[密鑰|對稱加密算法]
…… //繼續其它的通訊
複製代碼
2.7 其它問題:
上面的過程已經十分接近HTTPS的真實通訊過程了,徹底能夠按照這個過程去理解HTTPS的工做原理。可是我爲了方便解釋,上面有些細節沒有說到,有興趣的人能夠看下這部分的內容。能夠跳過不看,可有可無。
【問題1】
上面的通訊過程當中說到,在檢查完證書後,「客戶」發送一個隨機的字符串給「服務器」去用私鑰加密,以便判斷對方是否真的持有私鑰。可是有一個問題,「黑客」也能夠發送一個字符串給「服務器」去加密而且獲得加密後的內容,這樣對於「服務器」來講是不安全的,由於黑客能夠發送一些簡單的有規律的字符串給「服務器」加密,從而尋找加密的規律,有可能威脅到私鑰的安全。因此說,「服務器」隨隨便便用私鑰去加密一個來路不明的字符串並把結果發送給對方是不安全的。
〖解決方法〗
每次收到「客戶」發來的要加密的的字符串時,「服務器」並非真正的加密這個字符串自己,而是把這個字符串進行一個hash計算,加密這個字符串的hash值(不加密原來的字符串)後發送給「客戶」,「客戶」收到後解密這個hash值並本身計算字符串的hash值而後進行對比是否一致。也就是說,「服務器」不直接加密收到的字符串,而是加密這個字符串的一個hash值,這樣就避免了加密那些有規律的字符串,從而下降被破解的機率。「客戶」本身發送的字符串,所以它本身能夠計算字符串的hash值,而後再把「服務器」發送過來的加密的hash值和本身計算的進行對比,一樣也能肯定對方是不是「服務器」。
【問題2】
在雙方的通訊過程當中,「黑客」能夠截獲發送的加密了的內容,雖然他沒法解密這個內容,可是他能夠搗亂,例如把信息原封不動的發送屢次,擾亂通訊過程。
〖解決方法〗
能夠給通訊的內容加上一個序號或者一個隨機的值,若是「客戶」或者「服務器」接收到的信息中有以前出現過的序號或者隨機值,那麼說明有人在通訊過程當中重發信息內容進行搗亂,雙方會馬上中止通訊。有人可能會問,若是有人一直這麼搗亂怎麼辦?那不是沒法通訊了? 答案是的確是這樣的,例若有人控制了你鏈接互聯網的路由器,他的確能夠針對你。可是一些重要的應用,例如軍隊或者政府的內部網絡,它們都不使用咱們平時使用的公網,所以通常人不會破壞到他們的通訊。
【問題3】
在雙方的通訊過程當中,「黑客」除了簡單的重複發送截獲的消息以外,還能夠修改截獲後的密文修改後再發送,由於修改的是密文,雖然不能徹底控制消息解密後的內容,可是仍然會破壞解密後的密文。所以發送過程若是黑客對密文進行了修改,「客戶」和「服務器」是沒法判斷密文是否被修改的。雖然不必定能達到目的,可是「黑客」能夠一直這樣碰碰運氣。
〖解決方法〗
在每次發送信息時,先對信息的內容進行一個hash計算得出一個hash值,將信息的內容和這個hash值一塊兒加密後發送。接收方在收到後進行解密獲得明文的內容和hash值,而後接收方再本身對收到信息內容作一次hash計算,與收到的hash值進行對比看是否匹配,若是匹配就說明信息在傳輸過程當中沒有被修改過。若是不匹配說明中途有人故意對加密數據進行了修改,馬上中斷通話過程後作其它處理。
http://www.cnblogs.com/JeffreySun/archive/2010/06/24/1627247.html#!comments