為什么用公鑰加密卻不能用公鑰解密?
大家第一次接觸HTTPS的時候是不是和我一樣,非常困惑。
這玩意概念又多又繁瑣。尤其是里面的公鑰私鑰啥的。
當(dāng)時我就特別想知道,為什么用公鑰加密卻不能用公鑰解密?
看完這篇文章你會弄明白,同時還會解鎖很多HTTPS里的細(xì)節(jié)知識點(diǎn)。
今天,我們就先從對稱加密和非對稱加密聊起吧。
對稱加密和非對稱加密
小學(xué)上課的時候,都傳過小紙條吧?傳紙條的時候每個拿到紙條的同學(xué)都會忍不住看一眼,毫無隱私可言。
假設(shè)班花想對我表白,又不想在傳的過程中讓別人發(fā)現(xiàn)她的情意綿綿。
就會在課間十分鐘里告訴我,"每個字母向左移動一位,就是我想對你說的話"。
然后在上課的時候,遞出紙條,上面寫了 eb tib cj。每個幫助傳遞紙條的同學(xué)看了之后,都暗罵“謎語人,你給我滾出哥譚鎮(zhèn)”。
嘿嘿,你們不懂,我懂。
我拿到紙條后,將每個字母向左移動一位,得到 da sha bi。
什么話,這是什么話。
壞女人想要?dú)蚁虻乐??我果斷拒絕了她的表白。
現(xiàn)在回憶起來,感動之余,會發(fā)現(xiàn),像這種,將一段大家看得懂的信息(明文)轉(zhuǎn)換為另一段大家看不懂的信息(密文),其實就是加密。
像這種“左移”的加密方法,其實就是所謂的秘鑰。而這種加密和解密用的都是同一個秘鑰的加密形式,就叫對稱加密。
對稱加密
那既然有對稱加密,那就有非對稱加密。
不同點(diǎn)在于,非對稱加密,加密和解密用到的不是同一個秘鑰,而是兩個不一樣的秘鑰,分別是公鑰和私鑰。
非對稱加密
公鑰負(fù)責(zé)加密,私鑰負(fù)責(zé)解密。公鑰人人可得,私鑰永遠(yuǎn)不泄露。<br>。
那么問題就來了。
為什么用公鑰加密,卻不能用公鑰解密?
這其實就涉及到公鑰和私鑰加密的數(shù)學(xué)原理了。
說白了加密就是將一個已知的數(shù)字根據(jù)一定的規(guī)則轉(zhuǎn)換變成另一個數(shù)字,以前這些數(shù)字放在一起都可讀,但是經(jīng)過這么一轉(zhuǎn)換,就變得不可讀了。
也就是說加密的本質(zhì)就是 num -> x (num是已知數(shù),x是未知數(shù))。
比如班花操作的加一減一就是很簡單的轉(zhuǎn)換方式。
那我們換個復(fù)雜的,比如求余運(yùn)算。
假設(shè)現(xiàn)在有個求余運(yùn)算公式。
這個公式就很簡單。在已知5的2次方和7的情況下,很容易得到x=4。
但是如果我們換一下x的位置。
求x等于多少的時候,上面的等式能成立呢?
那就麻煩多了。
雖然麻煩了一些,但還是能反推得到x=2時等式成立。
但如果上面的模數(shù)字變得巨大無比呢?
那這時候計算機(jī)只能挨個去試才能算出。正常CPU要跑好多年才能算出來,所以可以認(rèn)為算不出來。
其實上面的公式就是將 5 加密成了4。如果已知x,就很容易算出等式右邊的結(jié)果是4,而反過來,從4卻難以反推得到出x的值是多少。因此說這樣的取模算法是不可逆的。
雖然取模運(yùn)算是不可逆的,但是結(jié)合歐拉定理,卻可以讓這個公式在一定條件下變得有點(diǎn)“可逆”(注意是加了引號的)。
我們來看下是怎么做的。
我們將x掰成兩瓣,變成p和q的乘積。
如果p, q?, N選取得當(dāng),原文一波取模操作之后還是變回原文。
知道這個沒用,但是結(jié)合歐拉定理,再經(jīng)過一些我們都看不懂的推導(dǎo)過程,就可以將上面的公式變換成下面這樣。
結(jié)合歐拉公式的計算過程大家感興趣可以查查。但這里只知道結(jié)論就夠了。
也就是說,知道 p?就能加密,知道 q就能解密。
而這里的p就是公鑰,q就是私鑰。
用公鑰加密過的密文只有用私鑰才能解密。?
加密解密公式
而且更妙的是。
p和q其實在公式里位置是可以互換的,所以反過來說“用私鑰加密過的密文,只有公鑰才能解密”,也是ok的。而這種操作,就是常說的驗證數(shù)字簽名。
這就像以前古裝電視劇里,經(jīng)常有這么個劇情,兩個失散多年的親人,各自身上帶有一塊碎成兩瓣的玉佩。哪天他們發(fā)現(xiàn)兩塊玉佩裂痕正好可以拼在一起,那就確認(rèn)了對方就是自己失散多年的好大兒。
這兩塊碎玉,就有點(diǎn)公鑰和私鑰的味道。
公鑰和私鑰的關(guān)系
原理大家知道這么多其實就夠了。
看到這里,我們就能回答標(biāo)題的問題了。
為什么用公鑰加密,卻不能用公鑰解密??
因為大數(shù)取模運(yùn)算是不可逆的,因此他人無法暴力解密。但是結(jié)合歐拉定理,我們可以選取出合適的p(公鑰), q(私鑰), N(用于取模的大數(shù)),讓原本不可逆的運(yùn)算在特定情況下,變得有那么點(diǎn)“可逆”的味道。數(shù)學(xué)原理決定了我們用公鑰加密的數(shù)據(jù),只有私鑰能解密。反過來,用私鑰加密的數(shù)據(jù),也只有公鑰能解密。
從數(shù)學(xué)原理也能看出,公鑰和私鑰加密是安全的,但這件事情的前提是建立在"現(xiàn)在的計算機(jī)計算速度還不夠快"這個基礎(chǔ)上。因此,如果有一天科技變得更發(fā)達(dá)了,我們變成了更高維度的科技文明,可能現(xiàn)在的密文就跟明文沒啥區(qū)別了。
了解了對稱加密和非對稱機(jī)密之后,我們就可以聊聊HTTPS的加密原理了。
HTTPS的加密原理
如果你在公司內(nèi)網(wǎng)里做開發(fā),并且寫的代碼也只對內(nèi)網(wǎng)提供服務(wù)。那么大概率你的服務(wù)是用的HTTP協(xié)議。
但如果哪天你想讓外網(wǎng)的朋友們也體驗下你的服務(wù)功能,那就需要將服務(wù)暴露到外網(wǎng),而這時候如果還是用的HTTP協(xié)議,那信息的收發(fā)就會是明文,只要有心人士在通訊鏈路中任意一個路由器那抓個包,就能看到你HTTP包里的內(nèi)容,因此很不安全。
為了讓明文,變成密文,我們需要在HTTP層之上再加一層TLS層,目的就是為了做個加密。這就成了我們常說的HTTPS。
TLS其實分為1.2和1.3版本,目前主流的還是1.2版本,我們以它為例,來看下HTTPS的連接是怎么建立的。
HTTPS握手過程
首先是建立TCP連接,畢竟HTTP是基于TCP的應(yīng)用層協(xié)議。
在TCP成功建立完協(xié)議后,就可以開始進(jìn)入HTTPS的加密流程。
總的來說。整個加密流程其實分為兩階段。
加密的兩階段
?第一階段是TLS四次握手,這一階段主要是利用非對稱加密的特性各種交換信息,最后得到一個"會話秘鑰"。
第二階段是則是在第一階段的"會話秘鑰"基礎(chǔ)上,進(jìn)行對稱加密通信。
我們先來看下第一階段的TLS四次握手是怎么樣的。
HTTPS流程
第一次握手:
- Client Hello:是客戶端告訴服務(wù)端,它支持什么樣的加密協(xié)議版本,比如 TLS1.2,使用什么樣的加密套件,比如最常見的RSA,同時還給出一個客戶端隨機(jī)數(shù)。
第二次握手:
?Server Hello:服務(wù)端告訴客戶端,服務(wù)器隨機(jī)數(shù) + 服務(wù)器證書 + 確定的加密協(xié)議版本(比如就是TLS1.2)。
第三次握手:
?Client Key Exchange: 此時客戶端再生成一個隨機(jī)數(shù),叫 pre_master_key 。從第二次握手的服務(wù)器證書里取出服務(wù)器公鑰,用公鑰加密 pre_master_key,發(fā)給服務(wù)器。
?Change Cipher Spec: 客戶端這邊已經(jīng)擁有三個隨機(jī)數(shù):客戶端隨機(jī)數(shù),服務(wù)器隨機(jī)數(shù)和pre_master_key,用這三個隨機(jī)數(shù)進(jìn)行計算得到一個"會話秘鑰"。此時客戶端通知服務(wù)端,后面會用這個會話秘鑰進(jìn)行對稱機(jī)密通信。
?Encrypted Handshake Message:客戶端會把迄今為止的通信數(shù)據(jù)內(nèi)容生成一個摘要,用"會話秘鑰"加密一下,發(fā)給服務(wù)器做校驗,此時客戶端這邊的握手流程就結(jié)束了,因此也叫Finished報文。
第四次握手:
?Change Cipher Spec:服務(wù)端此時拿到客戶端傳來的 pre_master_key(雖然被服務(wù)器公鑰加密過,但服務(wù)器有私鑰,能解密獲得原文),集齊三個隨機(jī)數(shù),跟客戶端一樣,用這三個隨機(jī)數(shù)通過同樣的算法獲得一個"會話秘鑰"。此時服務(wù)器告訴客戶端,后面會用這個"會話秘鑰"進(jìn)行加密通信。
?Encrypted Handshake Message:跟客戶端的操作一樣,將迄今為止的通信數(shù)據(jù)內(nèi)容生成一個摘要,用"會話秘鑰"加密一下,發(fā)給客戶端做校驗,到這里,服務(wù)端的握手流程也結(jié)束了,因此這也叫Finished報文。
短短幾次握手,里面全是細(xì)節(jié),沒有一處是多余的。
我們一個個來解釋。
因為大家肯定已經(jīng)很暈了,所以我會盡量用簡短的語句,來解釋下面幾個問題。
HTTPS到底是對稱加密還是非對稱機(jī)密?
都用到了。前期4次握手,本質(zhì)上就是在利用非對稱加密的特點(diǎn),交換三個隨機(jī)數(shù)。
目的就是為了最后用這三個隨機(jī)數(shù)生成對稱加密的會話秘鑰。后期就一直用對稱機(jī)密的方式進(jìn)行通信。
對稱加密還是非對稱加密
為什么不都用非對稱加密呢?
因為非對稱加密慢,對稱加密相對來說快一些。
第二次握手里的服務(wù)器證書是什么?怎么從里面取出公鑰?
?服務(wù)器證書,本質(zhì)上是,被權(quán)威數(shù)字證書機(jī)構(gòu)(CA)的私鑰加密過的服務(wù)器公鑰。
服務(wù)器證書是什么
上面提到過,被私鑰加密過的數(shù)據(jù),是可以用公鑰來解密的。而公鑰是任何人都可以得到的。所以第二次握手的時候,客戶端可以通過CA的公鑰,來解密服務(wù)器證書,從而拿到藏在里面的服務(wù)器公鑰。?
用CA公鑰解密證書
看起來好像有點(diǎn)多此一舉?
那么問題來了。
為什么我不能只傳公鑰,而要拿CA的私鑰加密一次再傳過去?
反過來想想,如果只傳公鑰,公鑰就有可能會在傳輸?shù)倪^程中就被黑客替換掉。然后第三次握手時客戶端會拿著假公鑰來加密第三個隨機(jī)數(shù) pre_master_key?,黑客解密后自然就知道了最為關(guān)鍵的 pre_master_key。又因為第一和第二個隨機(jī)數(shù)是公開的,因此就可以計算出"會話秘鑰"。
所以需要有個辦法證明客戶端拿到的公鑰是真正的服務(wù)器公鑰,于是就拿CA的私鑰去做一次加密變成服務(wù)器證書,這樣客戶端拿CA的公鑰去解密,就能驗證是不是真正的服務(wù)器公鑰。
那么問題又又來了
怎么去獲得CA的公鑰?
最容易想到的是請求CA的官網(wǎng),獲取公鑰。但全世界要上網(wǎng)的人那么多,都用去請求CA官網(wǎng)的話,官網(wǎng)肯定頂不住。
考慮到能頒發(fā)證書的CA機(jī)構(gòu)可不多,因此對應(yīng)的CA公鑰也不多,把他們直接作為配置放到操作系統(tǒng)或者瀏覽器里,這就完美解決了上面的問題。
CA公鑰內(nèi)置于操作系統(tǒng)或瀏覽器中
別人就拿不到你這三個隨機(jī)數(shù)?
這三個隨機(jī)數(shù),兩個來自客戶端,一個來自服務(wù)端。第一次和第二次握手里的客戶端隨機(jī)數(shù)和服務(wù)端隨機(jī)數(shù),都是明文的。只要有心,大家都能拿到。
但第三個隨機(jī)數(shù) pre_master_key 則不行,因為它在客戶端生成后,發(fā)給服務(wù)器之前,被服務(wù)器的公鑰加密過,因此只有服務(wù)器本器才能用私鑰進(jìn)行解密。就算被別人拿到了,沒有服務(wù)器的私鑰,也無法解密出原文。
pre_master_key的加密解密
為什么要用三個隨機(jī)數(shù)?而不是一個或兩個?
三個隨機(jī)數(shù)生成對稱秘鑰
看上去第三個隨機(jī)數(shù) pre_master_key才是關(guān)鍵,另外兩個看起來可有可無?
確實,就算沒有另外兩個,也并不影響加密功能。之所以還要兩個隨機(jī)數(shù),是因為只有單個 pre_master_key隨機(jī)性不足,多次隨機(jī)的情況下有可能出來的秘鑰是一樣的。但如果再引入兩個隨機(jī)數(shù),就能大大增加"會話秘鑰"的隨機(jī)程度,從而保證每次HTTPS通信用的會話秘鑰都是不同的。
為什么第三和第四次握手還要給個摘要?
第三和第四次握手的最后都有個 Finished報文,里面是個摘要。
摘要,說白了就是對一大段文本進(jìn)行一次hash操作。目的是為了確認(rèn)通信過程中數(shù)據(jù)沒被篡改過。
第三次握手,客戶端生成摘要,服務(wù)端驗證,如果驗證通過,說明客戶端生成的數(shù)據(jù)沒被篡改過,服務(wù)端后面才能放心跟客戶端通信。
第四次握手,則是反過來,由服務(wù)端生成摘要,客戶端來驗證,驗證通過了,說明服務(wù)端是可信任的。
那么問題叒來了。
為什么要hash一次而不是直接拿原文進(jìn)行對比?
這是因為原文內(nèi)容過長,hash之后可以讓數(shù)據(jù)變短。更短意味著更小的傳輸成本。
摘要算法
這個過程中到底涉及了幾對私鑰和公鑰?
兩對。
?服務(wù)器本身的公鑰和私鑰:在第二次握手中,服務(wù)器將自己的公鑰(藏在數(shù)字證書里)發(fā)給客戶端。第三次握手中用這個服務(wù)器公鑰來加密第三個隨機(jī)數(shù) pre_master_key。服務(wù)器拿到后用自己的私鑰去做解密。
CA的公鑰和私鑰:第二次握手中,傳的數(shù)字證書里,包含了被CA的私鑰加密過的服務(wù)器公鑰??蛻舳四玫胶螅瑫脤崿F(xiàn)內(nèi)置在操作系統(tǒng)或瀏覽器里的CA公鑰去進(jìn)行解密。
總結(jié)
- 大數(shù)取模運(yùn)算是不可逆的,因此他人無法暴力解密。但是結(jié)合歐拉定理,我們可以選取出合適的p(公鑰), q(私鑰), N(用于取模的大數(shù)),讓原本不可逆的運(yùn)算在特定情況下,變得有那么點(diǎn)“可逆”的味道。數(shù)學(xué)原理決定了我們用公鑰加密的數(shù)據(jù),只有私鑰能解密。反過來,用私鑰加密的數(shù)據(jù),也只有公鑰能解密。
- HTTPS相當(dāng)于HTTP+TLS,目前主流的是TLS1.2,基于TCP三次握手之后,再來TLS四次握手。
- TLS四次握手的過程中涉及到兩對私鑰和公鑰。分別是服務(wù)器本身的私鑰和公鑰,以及CA的私鑰和公鑰。
- TLS四次握手背起來會挺難受的,建議關(guān)注三個隨機(jī)數(shù)的流向,以此作為基礎(chǔ)去理解,大概就能記下來了。