大話https演化過程(包括概念:對稱加密、非對稱加密、公鑰、私鑰、數字簽名、數字證書、https訪問全過程)
在網絡上發送數據是非常不安全的,非常容易被劫持或是被篡改,所以每次定向發送數據你都可以視為在廣播,每次定向接收數據都可以視為在廣收。而建立安全通道的難度和成本都很高,甚至安全性都不一定靠譜。
在這樣的情境下,F需要向S發送一段只有S才能看的信息msg,它要如何做呢?
很容易想到一個最直接的方法:給這段信息加密,只有F和S有密鑰(加密與解密采用相同的算法和密鑰),這樣F廣播的信息雖然都能看到,但是只有S才能解密看懂
- 這個方法不用我說也肯定哪兒有問題:F的密鑰是怎么傳到S手上的呢?(密鑰也是一段數據,也有被劫持的風險)
於是這個方法輕易地跌入了死循環的陷阱,那怎么辦呢,看起來好像事情陷入了僵局。但牛逼的密碼學家想到了一個妙招,他們發明了一種神奇的鑰匙,用這種神奇的鑰匙打破了僵局
- 神奇的鑰匙不是一把,而是一套兩把,比如A和B,它們的特點是:A加密的數據只有B能解密,B加密的數據只有A能解密(這是怎么實現的又是另外一回事,可以另外看相關的數學資料)
- 是這樣通過神奇鑰匙來解決問題的:(如果F需要向S發送一段只有S才能看的信息msg)
- 先分配給接收者S一套神奇鑰匙,然后S留一把給自己,叫做私鑰,比如sA,這把鑰匙不公開,只給自己使用,另一把鑰匙S通過廣播發送給F(甚至是所有人),比如sB,這把鑰匙不僅隨便你怎么劫持,甚至干脆公開,所有人都可以使用,叫做公鑰
- 然后F收到公鑰sB后,把要發送的msg用sB加密,再把密文msg通過廣播發送給S
- S收到密文msg后,使用sA進行解密,閱讀到內容
- 因為在互相傳送的過程中,只有公鑰sB和用sB加密的密文msg被廣播了,即使他們都被劫持,劫持者也無法對msg進行解密,關鍵的能解密的鑰匙sA一直好好地呆在S手上,計划通
這個方法不僅看起來非常巧妙,而且看起來也完美無缺,但即使如此,非常遺憾,它也存在問題,而且是兩個問題,雖然確切地說是一類問題
- 其實最開始的要求【F需要向S發送一段只有S才能看的信息msg】由於網絡的不安全性,它具體包括兩個方面
- 不能被偷看。除S之外的其他人無法閱讀msg
- 不能被篡改。收到的msg確實是F發的原版msg,不是假的或者修改過的
- 你確實解決了第一個方面,但是第二個方面你完全不能防范,因為雖然劫持者得到的公鑰sB不能對密文msg進行解密,但劫持者可以用公鑰sB來偽造另一份jmsg,然后裝作是F發送的msg送給S,S能對這個jmsg解密,而且解密之后並不能區分它是不是真的,假信息同樣能對S造成危險(比如讓S給某個賬號打錢)
- 甚至由於同樣的原因,你有沒有惡寒地意識到另外一種危險的可能,那就是:最初F收到的公鑰sB會不會是偽造的呢?
- 這樣的話,其實你剛剛以為解決的第一個方面其實也沒有解決,因為:假如最初F收到的公鑰sB其實是劫持者發過來的假公鑰jB,那么F就會用這個jB來對他要發送的msg進行加密,加密后廣播發出去,被劫持者劫持后他就能使用他的jA來解密,竊取信息,任務失敗。(不考慮 最初F會收到多份公鑰、最后S收到的密文msg用sA無法解密 會引起懷疑,因為這個時候msg已經泄露了,而且引起懷疑之后問題還是在,還是需要解決)
這兩個問題中其中一個問題比較好解決:確定【S收到的信息msg確實是F發送的】,沒有被篡改,也就是信息要能確定地標識自己的身份
- 好像能利用神奇鑰匙的另一個特點來解決問題:使用AB鑰匙配對的唯一性來標識身份。大概是這樣的:
- 當發送者用私鑰對信息進行加密后,接收者發現公鑰可以把接收的信息解密,這就說明收到的信息跟公鑰的主人是同一個人(假如收到的公鑰確實是他希望的發送者發來的話)
- 所以這里就可以具體這樣做:
- 給F一套它的神奇鑰匙,F把fA作為私鑰,fB作為公鑰
- F發送msg時,用它的私鑰fA和S的公鑰sB對msg進行雙重加密
- S收到信息msg后,先用fB對msg進行解密,確定這條信息就是F發送來的,再用自己的私鑰再次解密以讀取信息
上面這個方法公鑰身份的問題同樣懸而未決,所以回到前面,最大的問題還是:如何確定【F收到的公鑰sB確實是S發送的】,每一個公鑰sB要能確定地標識自己的身份
- 簡單用上面同樣的方法想一下:
- S發送自己的公鑰sB前,要先用自己的私鑰sA對這個公鑰sB加密;之后F收到經過sA加密的公鑰sB后,如果使用sB能把它解密,那就說明這個被加密的信息確實是S發來的
- 哈哈等等,你看的時候就發現了一個很大的不對勁吧,是的,這里又出現了循環,而且非常明顯:F在收到sB之前並不能對經過sA加密的信息解密,即使這個被加密的信息中就是sB,所以這個傳送sB的方法行不通
那怎么辦?明着傳公鑰會不知道是誰的,把身份加密進去傳公鑰對方又解不開密。身份肯定是要標識的,那不用加密的方式標識身份,換種方式標識行不行啊?這樣對方確認身份的時候就不用解密,就不用擔心對方沒密鑰解不了密了
如果不行的話那就只剩一個方法了,事先傳公鑰的時候要不就用一下安全通道嘞?是的,前面說的【建立安全通道的難度和成本都很高,甚至安全性都不一定靠譜】這幾個問題其實是可以通過拆分然后逐個攻破的
- 可拆分成這兩個維度:(這兩個維度其實也是安全領域內兩個永恆的主題)安全性和付出成本
- 安全性方面
- 對於個人用戶來說,你確實你難以在網絡上構建一條安全通道(因為你不是專業的搞安全的),但是如果你有一個靠譜的第三方機構的協助,你還是可能實現的
- 比如你把你的公鑰發布到第三方機構,然后想發送給你信息的人先去第三方機構上下載你的公鑰,這樣你的公鑰就通過一條安全通道傳給了別人
- 付出成本方面
- 如果只是像上一條這樣用這種方法構建安全通道的話,情況是這樣的:(假如F要發送信息給S)
- 那么S要事先把自己的公鑰發布到第三方機構,F也要事先把自己的公鑰發布到第三方機構
- 然后F在發送之前先上第三方機構獲取S的公鑰,之后F把信息用S的公鑰加密,再用自己的私鑰加密
- 然后F把雙重加密后的信息發送給S
- S收到信息后要先上第三方機構獲取F的公鑰,之后把收到的信息用F的公鑰解密確認是F發的信息,再用自己的私鑰解密讀取數據
- 它會面臨這些問題:
- 第三方機構需要實時維護一個巨大的公鑰庫,而且越來越大,存儲和流量都是問題
- F給不同的對象發送信息,都要事先上第三方機構獲取各種證書,而不能一次布置永久生效
- 正處於A和B連接過程中的時候,還需要另外去另一個地方C獲取某個東西,非常麻煩
- 所以這種利用第三方機構構建安全通道的方法需要一些改進
- 如果只是像上一條這樣用這種方法構建安全通道的話,情況是這樣的:(假如F要發送信息給S)
聰明的密碼學家想到了這個辦法:(假如F要發送信息給S)
- 事先F和S都上第三方機構獲取第三方機構的公鑰
- 事先F和S都把自己的公鑰發給第三方機構,然后第三方機構對他們的公鑰用第三方機構的私鑰進行加密,得到被加密的公鑰叫做F和S的數字證書,返回給F和S
- F先向S請求要S的數字證書
- 於是S把自己的數字證書發送給F
- F使用第三方的公鑰對數字證書進行解密,得到沒有錯的S的公鑰【為什么沒有錯?下面要講】
- 然后F就使用S的這個公鑰對要發送的信息進行加密,再用F自己的私鑰對這個信息二次加密,同時附上自己的數字證書。F把這些信息一塊發給S
- S在收到信息后首先解密數字證書獲得了F的公鑰,然后用這個公鑰對信息一次解密,能解開就說明發送信息的人是證書里寫的這個人,假如證書里寫的是F,那么就確定了F的身份,然后再用自己的私鑰對信息進行二次解密,讀取信息
- (這里其實有點像前面說的,在公鑰上套一個數字證書,標識了其身份,然后不用懷疑來懷疑去了,但為什么數字證書就信了呢?)
為什么用第三方的公鑰對數字證書進行解密這一過程能保證公鑰的身份呢?
- 這個問題嚴格說來,情境是這樣的:在你登錄網站A時,收到一份使用數字證書私鑰加密的公鑰,如何能證明證書里邊的公鑰是網站A的公鑰?
- 信任鏈條是這樣的:
- 你最開始要知道數字證書里邊是什么東西,主要有這兩個匹配的東西:網站地址和網站的公鑰
- 首先你電腦里記錄了所有能信任的頒發數字證書的公司以及他們的公鑰,這是你信任的基石,就像肯·湯普遜在他的《對深信不疑的信任》1983年獲得圖靈獎時的演說中說的一樣:你最終還是要絕對信任某一人,在這個問題上沒有第二條路可走
- 然后第一步,你檢查這份證書是不是你信任的公司頒發的,如果是,使用公鑰對這份證書進行解密,然后下一步
- 第二步,解密的結果是一個網站地址和網站公鑰,現在,你只要核對網站地址和你現在登錄的網站A是不是一個,如果是一個的話,那么證書里的這份公鑰就是A網站的
但實際情況還在此基礎上做了兩次改進
- 對於客戶來說,去第三方機構申請證書未免太繁瑣了,而且這個成本什么的。。。而其實客戶端可以不用證書的,因為可以用用戶名和密碼來校驗身份
- A是服務器,B是客戶
- B要登錄A網站,B先獲取A的證書(不管證書從哪里來的,它都能用你有的第三方公鑰解密來分辨)
- 然后B對A的證書用第三方公鑰進行解密(你事先會有一個列表,是確信的一些第三方公鑰),得到A的公鑰(而且經過驗證這確實是A的)
- 然后B用A的公鑰對自己要發送的【用戶名和密碼和自己的公鑰】進行一次加密,把這密文發送給A
- A獲得信息之后直接用自己的私鑰解密,解密的內容中有 用戶名、密碼、用戶的公鑰
- 然后A只要驗證用戶名和密碼就能知道用戶的身份,然后確認這個公鑰是這個用戶的
- 接下來A發送數據就可以放心使用這個公鑰進行加密了
- 又因為非對稱加密非常消耗計算資源,所以客戶端干脆不用非對稱加密,然后只要建立好了SSL連接,雙方安全地擁有了一把對稱加密的鑰匙之后,就都使用對稱加密相互傳遞數據
- A是服務器,B是客戶
- A有A證書,有A公鑰和A私鑰,B開始什么都沒有,只持有第三方公鑰(后來生成了一個對稱密鑰)
- B要登錄A網站,B先獲取A的證書
- 然后B對A的證書用第三方公鑰進行解密,得到A的公鑰(而且經過驗證這確實是A的)
- 然后B用A的公鑰對自己要發送的【用戶名和密碼和自己臨時生成的一個對稱密鑰】進行加密,再把加密后的信息發送給A(外人沒有A的私鑰,所以這里傳遞對稱密鑰非常安全)
- A獲得信息之后直接用自己的私鑰解密,解密的內容中有 用戶名、密碼、對稱密鑰
- 然后A只要驗證用戶名和密碼就能知道用戶的身份,然后確認這個對稱密鑰是這個用戶的
- 之后只要這個SSL連接沒有關閉,后續的所有數據,無論是客戶端發出的還是服務器發出的,均會使用這個對稱密鑰加密
- (這里使用對稱密鑰的安全性也是有保障的,對稱加密算法中,依賴的是密鑰的保密性,只要密鑰沒有被泄露,對稱加密的結果被截獲也沒有什么意義。而密鑰是用公鑰加密的,只能由服務器解開)
雖然看起來上面這種方式已經讓https非常安全了,但其實還是有些問題的:
- 假如你要訪問網站A,那么一共有4種情況:
- 你要訪問網站A,然后訪問了網站A,網站A發送了一個網站A的證書給你
- 你要訪問網站A,然后訪問了網站A,網站A發送了一個網站B的證書給你
- 你要訪問網站A,但是訪問了類似釣魚網站B,網站B發送了一個網站B的證書給你(網站B神通廣大搞到一個證書)
- 你要訪問網站A,但是訪問了類似釣魚網站B,網站B自己沒有申請證書,只好發送一個網站A的證書給你
- 來分析一下:
- 第一種情況完全沒有問題
- 第二種情況,發生的概率很小,而且馬上就會報錯,不會有上面問題
- (從這里開始你要注意一下吊詭的地方,這兩種情況有釣魚網站B加入,危險慢慢降臨)
- 第四種情況,網頁會報錯,而且你確實是上了釣魚網站,看起來這個https起到作用了,它阻止了你瀏覽釣魚網站,阻止了你給他們發送自己的信息。但其實這種情況下,你不一定有危險,為什么呢,因為釣魚網站發給你的證書是網站A的證書,當你向這個網站的服務器發送信息的時候是你用了網站A的證書里的公鑰加密了你的用戶信息,然后發送給釣魚網站B,釣魚網站B雖然劫持了你發送來的信息,但是它並不是A網站,它沒有私鑰來對你的信息解密,這樣的話你的信息釣魚網站並不能獲取到(但其實這個時候我也不清楚釣魚網站會不會有其他手段,所以這種情況也可能因為其他原因而比較危險)
- 反倒是第三種情況,這時候你上了釣魚網站,但是網頁並不會報錯,因為網址和證書中的一致,https並不會阻止你上這個釣魚網站,而且由於你用了釣魚網站的公鑰對你的信息進行加密,所以釣魚網站可以對你的信息進行解密並獲取,這時候才是真正危險的時候
- 總結就是,使用https並不能完全保證你的上網安全,其中主要是你的原因,其次https也有部分原因,具體在使用https的時候如何避免泄露信息呢:
- 所有https告訴你這個證書被冒用時,你一定要好好檢查你的瀏覽器地址框,不要上錯了網站
- 即使https沒有告訴你證書被冒用,你也更加要好好檢查你的瀏覽器地址框,不要上錯了網站,這時候https並不能保護你
- 當https告訴你這個證書的頒發商不靠譜,你就也要小心,這可能有問題,也可能沒問題,但是你最好還是不要上
- 希望https的頒發機構們工作細致,不要給釣魚網站頒發證書