1、基礎(chǔ)知識
這部分內(nèi)容主要解釋一些概念和術(shù)語,最好是先理解這部分內(nèi)容。
1.1、公鑰密碼體制(public-key cryptography)
公鑰密碼體制分為三個部分,公鑰、私鑰、加密解密算法,它的加密解密過程如下:
加密:通過加密算法和公鑰對內(nèi)容(或者說明文)進(jìn)行加密,得到密文。加密過程需要用到公鑰。
解密:通過解密算法和私鑰對密文進(jìn)行解密,得到明文。解密過程需要用到解密算法和私鑰。注意,由公鑰加密的內(nèi)容,只能由私鑰進(jìn)行解密,也就是說,由公鑰加密的內(nèi)容,如果不知道私鑰,是無法解密的。
公鑰密碼體制的公鑰和算法都是公開的(這是為什么叫公鑰密碼體制的原因),私鑰是保密的。大家都以使用公鑰進(jìn)行加密,但是只有私鑰的持有者才能解密。在實際的使用中,有需要的人會生成一對公鑰和私鑰,把公鑰發(fā)布出去給別人使用,自己保留私鑰。
1.2、對稱加密算法(symmetric key algorithms)
在對稱加密算法中,加密使用的密鑰和解密使用的密鑰是相同的。也就是說,加密和解密都是使用的同一個密鑰。因此對稱加密算法要保證安全性的話,密鑰要做好保密,只能讓使用的人知道,不能對外公開。這個和上面的公鑰密碼體制有所不同,公鑰密碼體制中加密是用公鑰,解密使用私鑰,而對稱加密算法中,加密和解密都是使用同一個密鑰,不區(qū)分公鑰和私鑰。
// 密鑰,一般就是一個字符串或數(shù)字,在加密或者解密時傳遞給加密/解密算法。前面在公鑰密碼體制中說到的公鑰、私鑰就是密鑰,公鑰是加密使用的密鑰,私鑰是解密使用的密鑰。
1.3、非對稱加密算法(asymmetric key algorithms)
在非對稱加密算法中,加密使用的密鑰和解密使用的密鑰是不相同的。前面所說的公鑰密碼體制就是一種非對稱加密算法,他的公鑰和是私鑰是不能相同的,也就是說加密使用的密鑰和解密使用的密鑰不同,因此它是一個非對稱加密算法。
1.4、RSA簡介
RSA是一種公鑰密碼體制,現(xiàn)在使用得很廣泛。如果對RSA本身有興趣的,后面看我有沒有時間寫個RSA的具體介紹。
RSA密碼體制是一種公鑰密碼體制,公鑰公開,私鑰保密,它的加密解密算法是公開的。 由公鑰加密的內(nèi)容可以并且只能由私鑰進(jìn)行解密,并且由私鑰加密的內(nèi)容可以并且只能由公鑰進(jìn)行解密。也就是說,RSA的這一對公鑰、私鑰都可以用來加密和解密,并且一方加密的內(nèi)容可以由并且只能由對方進(jìn)行解密。
1.5、簽名和加密
我們說加密,是指對某個內(nèi)容加密,加密后的內(nèi)容還可以通過解密進(jìn)行還原。 比如我們把一封郵件進(jìn)行加密,加密后的內(nèi)容在網(wǎng)絡(luò)上進(jìn)行傳輸,接收者在收到后,通過解密可以還原郵件的真實內(nèi)容。
這里主要解釋一下簽名,簽名就是在信息的后面再加上一段內(nèi)容,可以證明信息沒有被修改過,怎么樣可以達(dá)到這個效果呢?一般是對信息做一個hash計算得到一個hash值,注意,這個過程是不可逆的,也就是說無法通過hash值得出原來的信息內(nèi)容。在把信息發(fā)送出去時,把這個hash值加密后做為一個簽名和信息一起發(fā)出去。 接收方在收到信息后,會重新計算信息的hash值,并和信息所附帶的hash值(解密后)進(jìn)行對比,如果一致,就說明信息的內(nèi)容沒有被修改過,因為這里hash計算可以保證不同的內(nèi)容一定會得到不同的hash值,所以只要內(nèi)容一被修改,根據(jù)信息內(nèi)容計算的hash值就會變化。當(dāng)然,不懷好意的人也可以修改信息內(nèi)容的同時也修改hash值,從而讓它們可以相匹配,為了防止這種情況,hash值一般都會加密后(也就是簽名)再和信息一起發(fā)送,以保證這個hash值不被修改。至于如何讓別人可以解密這個簽名,這個過程涉及到數(shù)字證書等概念,我們后面在說到數(shù)字證書時再詳細(xì)說明,這里您先只需先理解簽名的這個概念。
2、一個加密通信過程的演化
我們來看一個例子,現(xiàn)在假設(shè)“服務(wù)器”和“客戶”要在網(wǎng)絡(luò)上通信,并且他們打算使用RSA(參看前面的RSA簡介)來對通信進(jìn)行加密以保證談話內(nèi)容的安全。由于是使用RSA這種公鑰密碼體制,“服務(wù)器”需要對外發(fā)布公鑰(算法不需要公布,RSA的算法大家都知道),自己留著私鑰?!翱蛻簟蓖ㄟ^某些途徑拿到了“服務(wù)器”發(fā)布的公鑰,客戶并不知道私鑰。“客戶”具體是通過什么途徑獲取公鑰的,我們后面再來說明,下面看一下雙方如何進(jìn)行保密的通信:
2.1 第一回合:
“客戶”->“服務(wù)器”:你好
“服務(wù)器”->“客戶”:你好,我是服務(wù)器
“客戶”->“服務(wù)器”:????
因為消息是在網(wǎng)絡(luò)上傳輸?shù)模腥丝梢悦俺渥约菏恰胺?wù)器”來向客戶發(fā)送信息。例如上面的消息可以被黑客截獲如下:
“客戶”->“服務(wù)器”:你好
“服務(wù)器”->“客戶”:你好,我是服務(wù)器
“客戶”->“黑客”:你好 // 黑客在“客戶”和“服務(wù)器”之間的某個路由器上截獲“客戶”發(fā)給服務(wù)器的信息,然后自己冒充“服務(wù)器”
“黑客”->“客戶”:你好,我是服務(wù)器```
因此“客戶”在接到消息后,并不能肯定這個消息就是由“服務(wù)器”發(fā)出的,某些“黑客”也可以冒充“服務(wù)器”發(fā)出這個消息。如何確定信息是由“服務(wù)器”發(fā)過來的呢?有一個解決方法,因為只有服務(wù)器有私鑰,所以如果只要能夠確認(rèn)對方有私鑰,那么對方就是“服務(wù)器”。因此通信過程可以改進(jìn)為如下:
2.2 第二回合:
“客戶”->“服務(wù)器”:你好
“服務(wù)器”->“客戶”:你好,我是服務(wù)器
“客戶”->“服務(wù)器”:向我證明你就是服務(wù)器
“服務(wù)器”->“客戶”:你好,我是服務(wù)器 {你好,我是服務(wù)器}[私鑰|RSA]```
// 注意這里約定一下,{} 表示RSA加密后的內(nèi)容,[ | ]表示用什么密鑰和算法進(jìn)行加密,后面的示例中都用這種表示方式,例如上面的 {你好,我是服務(wù)器}[私鑰|RSA] 就表示用私鑰對“你好,我是服務(wù)器”進(jìn)行加密后的結(jié)果。
為了向“客戶”證明自己是“服務(wù)器”, “服務(wù)器”把一個字符串用自己的私鑰加密,把明文和加密后的密文一起發(fā)給“客戶”。對于這里的例子來說,就是把字符串 “你好,我是服務(wù)器”和這個字符串用私鑰加密后的內(nèi)容 {你好,我是服務(wù)器}[私鑰|RSA] 發(fā)給客戶。
“客戶”收到信息后,她用自己持有的公鑰解密密文,和明文進(jìn)行對比,如果一致,說明信息的確是由服務(wù)器發(fā)過來的。也就是說“客戶”把 {你好,我是服務(wù)器}[私鑰|RSA] 這個內(nèi)容用公鑰進(jìn)行解密,然后和“你好,我是服務(wù)器”對比。因為由“服務(wù)器”用私鑰加密后的內(nèi)容,由并且只能由公鑰進(jìn)行解密,私鑰只有“服務(wù)器”持有,所以如果解密出來的內(nèi)容是能夠?qū)Φ蒙系?,那說明信息一定是從“服務(wù)器”發(fā)過來的。
假設(shè)“黑客”想冒充“服務(wù)器”:
“客戶”->“黑客”:向我證明你就是服務(wù)器
“黑客”->“客戶”:你好,我是服務(wù)器 {你好,我是服務(wù)器}[???|RSA] //這里黑客無法冒充,因為他不知道私鑰,無法用私鑰加密某個字符串后發(fā)送給客戶去驗證。
“客戶”->“黑客”:????```
由于“黑客”沒有“服務(wù)器”的私鑰,因此它發(fā)送過去的內(nèi)容,“客戶”是無法通過服務(wù)器的公鑰解密的,因此可以認(rèn)定對方是個冒牌貨!
到這里為止,“客戶”就可以確認(rèn)“服務(wù)器”的身份了,可以放心和“服務(wù)器”進(jìn)行通信,但是這里有一個問題,通信的內(nèi)容在網(wǎng)絡(luò)上還是無法保密。為什么無法保密呢?通信過程不是可以用公鑰、私鑰加密嗎?其實用RSA的私鑰和公鑰是不行的,我們來具體分析下過程,看下面的演示:
2.3 第三回合:
```“客戶”->“服務(wù)器”:你好
“服務(wù)器”->“客戶”:你好,我是服務(wù)器
“客戶”->“服務(wù)器”:向我證明你就是服務(wù)器
“服務(wù)器”->“客戶”:你好,我是服務(wù)器 {你好,我是服務(wù)器}[私鑰|RSA]
“客戶”->“服務(wù)器”:{我的帳號是aaa,密碼是123,把我的余額的信息發(fā)給我看看}[公鑰|RSA]
“服務(wù)器”->“客戶”:{你的余額是100元}[私鑰|RSA]```
注意上面的的信息 {你的余額是100元}[私鑰],這個是“服務(wù)器”用私鑰加密后的內(nèi)容,但是我們之前說了,公鑰是發(fā)布出去的,因此所有的人都知道公鑰,所以除了“客戶”,其它的人也可以用公鑰對{你的余額是100元}[私鑰]進(jìn)行解密。所以如果“服務(wù)器”用私鑰加密發(fā)給“客戶”,這個信息是無法保密的,因為只要有公鑰就可以解密這內(nèi)容。然而“服務(wù)器”也不能用公鑰對發(fā)送的內(nèi)容進(jìn)行加密,因為“客戶”沒有私鑰,發(fā)送個“客戶”也解密不了。
這樣問題就又來了,那又如何解決呢?在實際的應(yīng)用過程,一般是通過引入對稱加密來解決這個問題,看下面的演示:
2.4 第四回合:
```“客戶”->“服務(wù)器”:你好
“服務(wù)器”->“客戶”:你好,我是服務(wù)器
“客戶”->“服務(wù)器”:向我證明你就是服務(wù)器
“服務(wù)器”->“客戶”:你好,我是服務(wù)器 {你好,我是服務(wù)器}[私鑰|RSA]
“客戶”->“服務(wù)器”:{我們后面的通信過程,用對稱加密來進(jìn)行,這里是對稱加密算法和密鑰}[公鑰|RSA] //藍(lán)色字體的部分是對稱加密的算法和密鑰的具體內(nèi)容,客戶把它們發(fā)送給服務(wù)器。
“服務(wù)器”->“客戶”:{OK,收到!}[密鑰|對稱加密算法]
“客戶”->“服務(wù)器”:{我的帳號是aaa,密碼是123,把我的余額的信息發(fā)給我看看}[密鑰|對稱加密算法]
“服務(wù)器”->“客戶”:{你的余額是100元}[密鑰|對稱加密算法]```
在上面的通信過程中,“客戶”在確認(rèn)了“服務(wù)器”的身份后,“客戶”自己選擇一個對稱加密算法和一個密鑰,把這個對稱加密算法和密鑰一起用公鑰加密后發(fā)送給“服務(wù)器”。注意,由于對稱加密算法和密鑰是用公鑰加密的,就算這個加密后的內(nèi)容被“黑客”截獲了,由于沒有私鑰,“黑客”也無從知道對稱加密算法和密鑰的內(nèi)容。
由于是用公鑰加密的,只有私鑰能夠解密,這樣就可以保證只有服務(wù)器可以知道對稱加密算法和密鑰,而其它人不可能知道(這個對稱加密算法和密鑰是“客戶”自己選擇的,所以“客戶”自己當(dāng)然知道如何解密加密)。這樣“服務(wù)器”和“客戶”就可以用對稱加密算法和密鑰來加密通信的內(nèi)容了。
總結(jié)一下,RSA加密算法在這個通信過程中所起到的作用主要有兩個:
因為私鑰只有“服務(wù)器”擁有,因此“客戶”可以通過判斷對方是否有私鑰來判斷對方是否是“服務(wù)器”。
客戶端通過RSA的掩護,安全的和服務(wù)器商量好一個對稱加密算法和密鑰來保證后面通信過程內(nèi)容的安全。
如果這里您理解了為什么不用RSA去加密通信過程,而是要再確定一個對稱加密算法來保證通信過程的安全,那么就說明前面的內(nèi)容您已經(jīng)理解了。(如果不清楚,再看下2.3和2.4,如果還是不清楚,那應(yīng)該是我們說清楚,您可以留言提問。)
到這里,“客戶”就可以確認(rèn)“服務(wù)器”的身份,并且雙方的通信內(nèi)容可以進(jìn)行加密,其他人就算截獲了通信內(nèi)容,也無法解密。的確,好像通信的過程是比較安全了。
但是這里還留有一個問題,在最開始我們就說過,“服務(wù)器”要對外發(fā)布公鑰,那“服務(wù)器”如何把公鑰發(fā)送給“客戶”呢?我們第一反應(yīng)可能會想到以下的兩個方法:
`a)把公鑰放到互聯(lián)網(wǎng)的某個地方的一個下載地址,事先給“客戶”去下載。`
`b)每次和“客戶”開始通信時,“服務(wù)器”把公鑰發(fā)給“客戶”。`
但是這個兩個方法都有一定的問題,
對于a)方法,“客戶”無法確定這個下載地址是不是“服務(wù)器”發(fā)布的,你憑什么就相信這個地址下載的東西就是“服務(wù)器”發(fā)布的而不是別人偽造的呢,萬一下載到一個假的怎么辦?另外要所有的“客戶”都在通信前事先去下載公鑰也很不現(xiàn)實。
對于b)方法,也有問題,因為任何人都可以自己生成一對公鑰和私鑰,他只要向“客戶”發(fā)送他自己的私鑰就可以冒充“服務(wù)器”了。示意如下:
“客戶”->“黑客”:你好 //黑客截獲“客戶”發(fā)給“服務(wù)器”的消息
“黑客”->“客戶”:你好,我是服務(wù)器,這個是我的公鑰 //黑客自己生成一對公鑰和私鑰,把公鑰發(fā)給“客戶”,自己保留私鑰
“客戶”->“黑客”:向我證明你就是服務(wù)器
“黑客”->“客戶”:你好,我是服務(wù)器 {你好,我是服務(wù)器}[黑客自己的私鑰|RSA] //客戶收到“黑客”用私鑰加密的信息后,是可以用“黑客”發(fā)給自己的公鑰解密的,從而會誤認(rèn)為“黑客”是“服務(wù)器”```
因此“黑客”只需要自己生成一對公鑰和私鑰,然后把公鑰發(fā)送給“客戶”,自己保留私鑰,這樣由于“客戶”可以用黑客的公鑰解密黑客的私鑰加密的內(nèi)容,“客戶”就會相信“黑客”是“服務(wù)器”,從而導(dǎo)致了安全問題。這里問題的根源就在于,大家都可以生成公鑰、私鑰對,無法確認(rèn)公鑰對到底是誰的。 如果能夠確定公鑰到底是誰的,就不會有這個問題了。例如,如果收到“黑客”冒充“服務(wù)器”發(fā)過來的公鑰,經(jīng)過某種檢查,如果能夠發(fā)現(xiàn)這個公鑰不是“服務(wù)器”的就好了。
為了解決這個問題,數(shù)字證書出現(xiàn)了,它可以解決我們上面的問題。先大概看下什么是數(shù)字證書,一個證書包含下面的具體內(nèi)容:
證書的有效期
公鑰
證書所有者(Subject)
簽名所使用的算法
指紋以及指紋算法```
證書的內(nèi)容的詳細(xì)解釋會在后面詳細(xì)解釋,這里先只需要搞清楚一點,數(shù)字證書可以保證數(shù)字證書里的公鑰確實是這個證書的所有者(Subject)的,或者證書可以用來確認(rèn)對方的身份。也就是說,我們拿到一個數(shù)字證書,我們可以判斷出這個數(shù)字證書到底是誰的。至于是如何判斷的,后面會在詳細(xì)討論數(shù)字證書時詳細(xì)解釋?,F(xiàn)在把前面的通信過程使用數(shù)字證書修改為如下:
2.5 第五回合:
“客戶”->“服務(wù)器”:你好
“服務(wù)器”->“客戶”:你好,我是服務(wù)器,這里是我的數(shù)字證書 //這里用證書代替了公鑰
“客戶”->“服務(wù)器”:向我證明你就是服務(wù)器
“服務(wù)器”->“客戶”:你好,我是服務(wù)器 {你好,我是服務(wù)器}[私鑰|RSA]```
注意,上面第二次通信,“服務(wù)器”把自己的證書發(fā)給了“客戶”,而不是發(fā)送公鑰?!翱蛻簟笨梢愿鶕?jù)證書校驗這個證書到底是不是“服務(wù)器”的,也就是能校驗這個證書的所有者是不是“服務(wù)器”,從而確認(rèn)這個證書中的公鑰的確是“服務(wù)器”的。后面的過程和以前是一樣,“客戶”讓“服務(wù)器”證明自己的身份,“服務(wù)器”用私鑰加密一段內(nèi)容連同明文一起發(fā)給“客戶”,“客戶”把加密內(nèi)容用數(shù)字證書中的公鑰解密后和明文對比,如果一致,那么對方就確實是“服務(wù)器”,然后雙方協(xié)商一個對稱加密來保證通信過程的安全。到這里,整個過程就完整了,我們回顧一下:
2.6 完整過程:
step1: “客戶”向服務(wù)端發(fā)送一個通信請求
“客戶”->“服務(wù)器”:你好
step2: “服務(wù)器”向客戶發(fā)送自己的數(shù)字證書。證書中有一個公鑰用來加密信息,私鑰由“服務(wù)器”持有
“服務(wù)器”->“客戶”:你好,我是服務(wù)器,這里是我的數(shù)字證書
step3: “客戶”收到“服務(wù)器”的證書后,它會去驗證這個數(shù)字證書到底是不是“服務(wù)器”的,數(shù)字證書有沒有什么問題,數(shù)字證書如果檢查沒有問題,就說明數(shù)字證書中的公鑰確實是“服務(wù)器”的。檢查數(shù)字證書后,“客戶”會發(fā)送一個隨機的字符串給“服務(wù)器”用私鑰去加密,服務(wù)器把加密的結(jié)果返回給“客戶”,“客戶”用公鑰解密這個返回結(jié)果,如果解密結(jié)果與之前生成的隨機字符串一致,那說明對方確實是私鑰的持有者,或者說對方確實是“服務(wù)器”。
“客戶”->“服務(wù)器”:向我證明你就是服務(wù)器,這是一個隨機字符串 //前面的例子中為了方便解釋,用的是“你好”等內(nèi)容,實際情況下一般是隨機生成的一個字符串。
“服務(wù)器”->“客戶”:{一個隨機字符串}[私鑰|RSA]
step4: 驗證“服務(wù)器”的身份后,“客戶”生成一個對稱加密算法和密鑰,用于后面的通信的加密和解密。這個對稱加密算法和密鑰,“客戶”會用公鑰加密后發(fā)送給“服務(wù)器”,別人截獲了也沒用,因為只有“服務(wù)器”手中有可以解密的私鑰。這樣,后面“服務(wù)器”和“客戶”就都可以用對稱加密算法來加密和解密通信內(nèi)容了。
“服務(wù)器”->“客戶”:{OK,已經(jīng)收到你發(fā)來的對稱加密算法和密鑰!有什么可以幫到你的?}[密鑰|對稱加密算法]
“客戶”->“服務(wù)器”:{我的帳號是aaa,密碼是123,把我的余額的信息發(fā)給我看看}[密鑰|對稱加密算法]
“服務(wù)器”->“客戶”:{你好,你的余額是100元}[密鑰|對稱加密算法]
…… //繼續(xù)其它的通信```
2.7 其它問題:
上面的過程已經(jīng)十分接近HTTPS的真實通信過程了,完全可以按照這個過程去理解HTTPS的工作原理。但是我為了方便解釋,上面有些細(xì)節(jié)沒有說到,有興趣的人可以看下這部分的內(nèi)容??梢蕴^不看,無關(guān)緊要。
【問題1】
上面的通信過程中說到,在檢查完證書后,“客戶”發(fā)送一個隨機的字符串給“服務(wù)器”去用私鑰加密,以便判斷對方是否真的持有私鑰。但是有一個問題,“黑客”也可以發(fā)送一個字符串給“服務(wù)器”去加密并且得到加密后的內(nèi)容,這樣對于“服務(wù)器”來說是不安全的,因為黑客可以發(fā)送一些簡單的有規(guī)律的字符串給“服務(wù)器”加密,從而尋找加密的規(guī)律,有可能威脅到私鑰的安全。所以說,“服務(wù)器”隨隨便便用私鑰去加密一個來路不明的字符串并把結(jié)果發(fā)送給對方是不安全的。
〖解決方法〗
每次收到“客戶”發(fā)來的要加密的的字符串時,“服務(wù)器”并不是真正的加密這個字符串本身,而是把這個字符串進(jìn)行一個hash計算,加密這個字符串的hash值(不加密原來的字符串)后發(fā)送給“客戶”,“客戶”收到后解密這個hash值并自己計算字符串的hash值然后進(jìn)行對比是否一致。也就是說,“服務(wù)器”不直接加密收到的字符串,而是加密這個字符串的一個hash值,這樣就避免了加密那些有規(guī)律的字符串,從而降低被破解的機率?!翱蛻簟弊约喊l(fā)送的字符串,因此它自己可以計算字符串的hash值,然后再把“服務(wù)器”發(fā)送過來的加密的hash值和自己計算的進(jìn)行對比,同樣也能確定對方是否是“服務(wù)器”。
【問題2】
在雙方的通信過程中,“黑客”可以截獲發(fā)送的加密了的內(nèi)容,雖然他無法解密這個內(nèi)容,但是他可以搗亂,例如把信息原封不動的發(fā)送多次,擾亂通信過程。
〖解決方法〗
可以給通信的內(nèi)容加上一個序號或者一個隨機的值,如果“客戶”或者“服務(wù)器”接收到的信息中有之前出現(xiàn)過的序號或者隨機值,那么說明有人在通信過程中重發(fā)信息內(nèi)容進(jìn)行搗亂,雙方會立刻停止通信。有人可能會問,如果有人一直這么搗亂怎么辦?那不是無法通信了? 答案是的確是這樣的,例如有人控制了你連接互聯(lián)網(wǎng)的路由器,他的確可以針對你。但是一些重要的應(yīng)用,例如軍隊或者政府的內(nèi)部網(wǎng)絡(luò),它們都不使用我們平時使用的公網(wǎng),因此一般人不會破壞到他們的通信。
【問題3】
在雙方的通信過程中,“黑客”除了簡單的重復(fù)發(fā)送截獲的消息之外,還可以修改截獲后的密文修改后再發(fā)送,因為修改的是密文,雖然不能完全控制消息解密后的內(nèi)容,但是仍然會破壞解密后的密文。因此發(fā)送過程如果黑客對密文進(jìn)行了修改,“客戶”和“服務(wù)器”是無法判斷密文是否被修改的。雖然不一定能達(dá)到目的,但是“黑客”可以一直這樣碰碰運氣。
〖解決方法〗
在每次發(fā)送信息時,先對信息的內(nèi)容進(jìn)行一個hash計算得出一個hash值,將信息的內(nèi)容和這個hash值一起加密后發(fā)送。接收方在收到后進(jìn)行解密得到明文的內(nèi)容和hash值,然后接收方再自己對收到信息內(nèi)容做一次hash計算,與收到的hash值進(jìn)行對比看是否匹配,如果匹配就說明信息在傳輸過程中沒有被修改過。如果不匹配說明中途有人故意對加密數(shù)據(jù)進(jìn)行了修改,立刻中斷通話過程后做其它處理。
>http://www.cnblogs.com/JeffreySun/archive/2010/06/24/1627247.html#!comments