<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          今天我抓了個 HTTPS 的包

          共 10898字,需瀏覽 22分鐘

           ·

          2021-09-17 05:37

          低并發(fā)編程
          戰(zhàn)略上藐視技術(shù),戰(zhàn)術(shù)上重視技術(shù)

          之前寫過一篇講 HTTPS 的思想的文章。

          破玩意 | 用 HTTPS 傳紙條

          后來又寫了篇用更凝練的語言總體描述了 HTTPS 的主干。

          叮咚 | HTTPS 的分支和主干

          想必通過這兩篇文章,HTTPS 為什么要這么設計,以及它是用來解決什么問題的,大家已經(jīng)心中有數(shù)了。

          那接下來就是細節(jié)了。

          由于之前已經(jīng)把思想講過了,本篇就通過抓包的方式,專注于 HTTPS 的過程,我會像個無情的流水賬一樣,給大家把一個 HTTPS 的包挖干凈。

          先普及一個知識點,HTTPS = TLS + HTTP。

          HTTP 我們很熟悉了,所以我們想知道的 HTTPS 的知識,本質(zhì)上是想知道 TLS 協(xié)議的規(guī)范,以及為什么這樣設計。所以我們本文展開講解 TLSv1.2 協(xié)議的內(nèi)容。

          我們開始吧!

          直接 postman 發(fā)起一個 HTTPS 的 POST 請求,這個 IP 是微博首頁。

          wireshark 抓包,過濾出 tls 協(xié)議的包,看到如下結(jié)果。

          一下就可以看到整個 HTTPS 握手的過程了。

          這個抓包數(shù)據(jù)可以加我好友,朋友圈有下載鏈接。但其實你自己隨便訪問一個網(wǎng)站用 wireshark 抓一下也行。

          學一個協(xié)議,最科學也是最方便的辦法,就是看官方文檔。

          我們看 TLS 1.2 的官方文檔,RFC-5246,其中 section-7.3 為我們描繪了整個握手過程。

          由于我們只是客戶端驗證服務端證書,而沒有服務端驗證客戶端證書的過程,所以我們的包里,是不包含 Server CertificateRequest(請求客戶端證書)、Client Certificate(客戶端證書)、CertificateVerify(客戶端證書有效性驗證)這三項的。

          下面我們一個一個過程拆開來看。


          ClientHello





          當 client 連接到一個 server 時,第一個發(fā)送的包就是它。

          具體包含以下內(nèi)容:

          client_version

          客戶端希望的,也是客戶端能支持的最高的 TLS 版本號,這里是 TLS 1.2 版本。

          random

          由客戶端生成的隨機數(shù),之后會用到,我們稱之為隨機數(shù) 1。

          ee8880e816ac14ca5b69bde656c188f37a08bcf2052a550b7867b041f6c1ab48

          session_id

          用于復用 TLS 連接,防止資源的浪費。但這個要服務端支持才行。

          cipher_suites

          客戶端支持的密碼學套件,按客戶端偏好排序,如果服務端沒有可支持的,那就回應錯誤(returns a handshake failure alert)并關(guān)閉連接。

          本次一共發(fā)了 18 個密碼學套件

          我們拿其中一個密碼學套件舉例

          TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256

          我們知道,HTTPS 的原理就是用非對稱加密的方式來交換秘鑰,用對稱加密的方式來通信,然后里面夾雜著哈希算法用于驗證簽名等。

          所以這個密碼學套件就包含了這三個部分。

          ECDHE_RSA 指的是秘鑰協(xié)商算法
          AES_128_GCM 是最終通信的對稱加密算法
          SHA256 是哈希算法

          以此來確定整個握手過程所需要的算法都用什么。

          compression_methods

          壓縮算法

          extensions

          擴展字段

          由此看出,本次 clientHello 最重要的信息就倆,一個隨機數(shù),一組支持的密碼學套件。

          接著往下看


          ServerHello





          服務端給客戶端發(fā)送的包,響應 ClientHello。

           具體包含以下內(nèi)容:

          server_version

          TLS 的版本,具體是服務端支持的最高版本以及客戶端支持的最低版本。

          random

          服務端生成的隨機數(shù),且生成規(guī)則不能依賴于客戶端的隨機數(shù),我們稱為隨機數(shù) 2。

          3ad03af5b8a5ebfe7902a250406b2e99d2667e37e524e0e5c333c0e0b9a637e8

          session_id

          服務端返回的會話 ID。

          如果客戶端剛剛發(fā)過來的 session_id 服務端已經(jīng)有了緩存,并且同意復用連接,則返回一個和客戶端剛剛發(fā)來的相同的 session_id。

          也可以發(fā)送一個新的 session_id,以便客戶端下次將其攜帶并且復用。

          也可以回復一個空值,表示不緩存 session_id,因此也不會復用。

          cipher_suite

          選擇的加密套件。

          剛剛客戶端傳來 18 個加密套件,服務端選擇了一個回應,此處回應的是。

          0xc02f

          表示

          TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256

          這個剛剛解釋過了,表示用 ECDHE_RSA 作為秘鑰交換算法,用 AES_128 作為通信時的對稱加密算法,用 SHA256 作為哈希算法。 

          compression_method

          選擇的壓縮算法,同上

          extensions

          擴展字段,同上

          由此看出,本次 serverHello 最重要的信息也是倆,和上面的 clientHello 一樣,也是一個隨機數(shù),還有一個從客戶端發(fā)來的一組密碼學套件中選擇的一個。

          至此,服務端和客戶端都擁有了隨機數(shù) 1 和隨機數(shù) 2,并且選定了共同確定的密碼學套件。

          雙方互相 hello 的過程就此結(jié)束了。

          接著往下看


          Server Certificate





          服務端發(fā)完上面的 ServerHello 后立即發(fā)這個包,這個包非常簡單。

          只有一個 Certificates 結(jié)構(gòu)體,就是我們常說的證書。

          而后綴還加了個 s,因此翻譯成證書鏈,是由一組證書組成的,最上面的是服務端本身的證書。

          我們把這個服務端的證書的關(guān)鍵信息都展開看一下:

          這個證書在默認情況下都是 X.509 格式的,除非明確協(xié)商說明。

          別懷疑,RFC-5246 中就是這樣寫的。

          這種格式的結(jié)構(gòu)定義在 RFC-1422 的 3.3 節(jié)中有說明。

          別廢話了,展開講一下吧。

          version

          證書版本號,v3

          serial number

          證書序列號,這個每個頒發(fā)機構(gòu)是唯一的,此處為:

          0x0de81066db219caef5ecb01ba273cad1

          signature

          簽名算法,僅僅是一個算法喲。

          此處是 1.2.840.113549.1.1.11

          表示 sha256WithRSAEncryption

          這就表示用 sha256 這個哈希算法對證書進行哈希生成摘要,然后再用 RSA 這個非對稱加密算法,用 CA 的私鑰加密剛剛生成的摘要,形成數(shù)字簽名。

          issuer name

          頒發(fā)者信息,我們展開看一下

          RDNSequence item: 1 item (id-at-countryName=US)
          RDNSequence item: 1 item (id-at-organizationName=DigiCert Inc)
          RDNSequence item: 1 item (id-at-organizationalUnitName=www.digicert.com)
          RDNSequence item: 1 item (id-at-commonName=GeoTrust CN RSA CA G1)


          validity period

          證書有效期,比如本案例中的

          notBefore: utcTime (0)
              utcTime20-06-09 00:00:00 (UTC)
          notAfter: utcTime (0)
              utcTime22-05-15 12:00:00 (UTC)


          subject name

          證書持有者信息

          rdnSequence: 5 items
              RDNSequence item: 1 item (id-at-countryName=CN)
                  RelativeDistinguishedName item (id-at-countryName=CN)
                      Id2.5.4.6 (id-at-countryName)
                      CountryName: CN
              RDNSequence item: 1 item (id-at-stateOrProvinceName=Beijing)
                  RelativeDistinguishedName item (id-at-stateOrProvinceName=Beijing)
                      Id2.5.4.8 (id-at-stateOrProvinceName)
                      DirectoryString: printableString (1)
              RDNSequence item: 1 item (id-at-organizationName=Sina.com Technology(China)Co.,ltd)
                  RelativeDistinguishedName item (id-at-organizationName=Sina.com Technology(China)Co.,ltd)
                      Id2.5.4.10 (id-at-organizationName)
                      DirectoryString: printableString (1)
              RDNSequence item: 1 item (id-at-organizationalUnitName=Sina.com Technology(China)Co.,ltd)
                  RelativeDistinguishedName item (id-at-organizationalUnitName=Sina.com Technology(China)Co.,ltd)
                      Id2.5.4.11 (id-at-organizationalUnitName)
                      DirectoryString: printableString (1)
              RDNSequence item: 1 item (id-at-commonName=weibo.cn)
                  RelativeDistinguishedName item (id-at-commonName=weibo.cn)
                      Id2.5.4.3 (id-at-commonName)
                      DirectoryString: printableString (1)
                          printableString: weibo.cn

          太亂了,簡化下就是

          countryName=CN
          stateOrProvinceName=Beijing
          organizationName=Sina.com Technology(China)Co.,ltd
          organizationalUnitName=Sina.com Technology(China)Co.,ltd
          commonName=weibo.cn

          顧名思義,就是微博網(wǎng)站這個頒發(fā)機構(gòu)的信息


          subject public key

          證書的公鑰信息,本案例中是:

          3082010a0282010100c4c84ff479214c5875037500cfc453d676cec0e64c7ab5f14e0284d8b49b6f23ec70f853d38eb60dc91a6fa826d49d188fd20158c3aaa101b4b6a0c89d4df824fe755ff2cfd4f876bb2dcefe760d6f9ec5e9e2990cab4367949f27062857ca26f2303f07f6c6c953f382cb8a379ae7b28c6234983fd61739550dc6b502c4feb9c9991459265f61471b91e3b592ad3e21a276d14321f462c820477e2b34a7ea16da1f3ffa760d9065ceb5a98ffc3d19da519133d542f74dd70c4366d98d16c36c27e4384cf31130614a1398621c64c260ad91d0de32900e2ac2589029b35d21eacd078bea5cb0a9db4bc3b7ba644d0459c2e0489ae62215cc525c36784191d94b0203010001

          除此之外,還剩下兩項,證書簽名算法(誒?這個剛剛不是已經(jīng)傳過了么),以及證書的簽名值

          從中可以讀出,簽名算法就是 sha256WithRSAEncryption,簽名值我提取出來,如下:

          220f0a0d15fa3c3909bb1e9f4d1d78cb9a41983cc9e549a4f8781f483fc18c679421eb84875354e00d86877eb1e80fb691eb0133208a0bee641ca0a7585b0e85818e88557a50f3f6241eebbc9cf49be40dc21f1d82a0cf30de30643cf236b290e74b6dee9bfdb71dab5f03b5cfd965bc16e139bc66f37119fcfc73aaf4c50fda1111bd948f507f85dd239012be73c953234328e332091c2fa38c482b6b4fdba52a26a1cc557a9c95edacea1d7b62f8996c934a5b3d762dd4f3cb88d405b805b7f604c07bd518665940f34fcb9e54121ac724a1ea3a58f42c9556f25058b19afa8c233fdf881bfeff32186051ec104fa23d4024b16b672f8eb33e359c3f813aa1

          至于它是怎么算出來的,之前也畫過一張圖,我就直接放過來了(注意,這里的給服務端,是指 CA 機構(gòu)給服務端,然后服務端現(xiàn)在又給了客戶端)。

          還記得剛剛的簽名算法么?sha256WithRSAEncryption

          這個圖里的哈希摘要用的算法就是 sha256,而 CA 私鑰加密用的算法就是 RSA。

          好了,全部證書相關(guān)的信息就講完了,同時也是 Server Certificate 這個環(huán)節(jié)的唯一信息。

          證書一方面可以通過服務端給客戶端傳遞的包解析來看,另一方面,由于瀏覽器要解析這個證書信息做驗證,所以通常瀏覽器有更直觀的方式可以查看,就不用我們費心思了。

          點開瀏覽器地址欄的小鎖頭。

          看,和我們剛剛抓包分析出來的信息,一毛一樣。

          我們繼續(xù)看下一個包。

          我相信你已經(jīng)不記得整個流程到哪里了,好心的我給你放之前的圖。

          剛剛進行完兩個 hello,以及一個傳遞證書的包 Certificate,接下來就要進行協(xié)商對稱秘鑰的過程了。

          這個過程,最簡單就是 RSA 算法,用服務端公鑰直接加密客戶端隨機生成的一個對稱加密秘鑰,發(fā)給服務端。

          但現(xiàn)在基本上都用更為復雜的秘鑰交換算法,我們往下看。


          Server Key Exchange





          用于 premaster secret 生成的

          之前說了,秘鑰交換算法是 ECDHE 算法,這里隱含著包含了好多信息。

          首先選擇的橢圓曲線是 named_curve 類型,并指定了基點
          生成一個私鑰,這個我們抓包看不見
          根據(jù)私鑰和基點,計算出公鑰,發(fā)送給客戶端,這個我們能看到,就是里面的 Pubkey,值為

          2ce174dbdb6f481b6ab9fd37446dca95b6ade3613afba03243d163360f63713b

          至于 ECDHE 用到的橢圓曲線秘鑰交換算法的細節(jié),這里就不展開講了,因為我也不會,就知道它最終是為了和服務端協(xié)商出來一個 premaster_secret 就好。

          接著往下看。


          Server CertificateRequest





          請求客戶端證書,此案例中沒有,一般銀行等需要客戶端也加密的才有,比如 U 盾。


          Server ServerHelloDone





          標識著 serverHello 這個握手過程結(jié)束了。


          Client Certificate





          客戶端證書。本案例中沒有,也說明了上面服務端確實沒有發(fā)送 CertificateRequest


          Client ClientKeyExchange





          緊接著 ServerHelloDone 發(fā)送,用于協(xié)商出 premaster_secret,同之前的 ServerKeyExchange 配合使用的。

          這回輪到客戶端給服務端一個用于 ECDHE 算法的公鑰了。

          f04e0743377afb5e9bf0a84aec5c7257957b85daee98fc48fb8971a26b457077

          而同時客戶端與這個公鑰配對的私鑰,我們也無法通過抓包看出來。


          生成最終通信的對稱加密秘鑰
          master_secret





          這一步不是抓包的信息,而是客戶端和服務端此時都在自己端內(nèi)所做的事情,非常關(guān)鍵。

          就是計算出最終對稱加密用的秘鑰 master_secret,這也是整個花里胡哨的過程,最終且唯一的一個目的,并且兩端算出來的結(jié)果肯定是一樣的。

          HTTPS 的目的,不就是雙方協(xié)商出一個共同的對稱加密秘鑰么,怕被中間人攔截到,所以做的證書呀,非對稱加密算法呀,秘鑰協(xié)商算法等復雜的規(guī)定。

          那 master_secret 是怎么計算出來的呢?

          還記不記得之前我們得到了三個隨機數(shù):

          隨機數(shù) 1(客戶端隨機數(shù)):在 ClientHello 消息里,由客戶端生成的隨機數(shù),是 ee8880e816ac14ca5b69bde656c188f37a08bcf2052a550b7867b041f6c1ab48
          隨機數(shù) 2(服務端隨機數(shù)):在 ServerHello 消息里,由服務端生成的隨機數(shù),是3ad03af5b8a5ebfe7902a250406b2e99d2667e37e524e0e5c333c0e0b9a637e8
          隨機數(shù) 3(pre_master):通過秘鑰交換算法 ECDHE 計算出的,我們叫它 pre_master。

          最終的對稱加密秘鑰 master_secret,就是根據(jù)這三個隨機數(shù)共同計算出來的。

          一旦雙方協(xié)商出來了這個相同的對稱秘鑰,那就可以開始愉快地安全通信了,TLS 層的工作也就圓滿完成。

          所以可想而知,接下來的工作,就都是收尾工作了,因為秘鑰已經(jīng)協(xié)商好了。


          Client CertificateVerify





          驗證客戶端證書有效性,本案例中沒有。


          Client ChangeCipherSpec





          秘鑰改變通知,此時客戶端已經(jīng)生成了 master_secret,之后的消息將都通過 master secret 來加密。

          可以看到,就是個標識,沒有攜帶什么有用的信息。


          Client Finish





          這一步對應的是 Client Finish 消息,客戶端將前面的握手消息生成摘要再用協(xié)商好的秘鑰加密,這是客戶端發(fā)出的第一條加密消息。服務端接收后會用秘鑰解密,能解出來說明前面協(xié)商出來的秘鑰是一致的。


          Server ChangeCipherSpec





          也是秘鑰改變通知,此時服務端也已經(jīng)生成了 master_secret 了,后面的通信都用此值加密。


          Server Finish





          同 Client Finish,服務器端發(fā)送握手結(jié)束通知,同時會帶上前面所發(fā)內(nèi)容的簽名到客戶端,保證前面通信數(shù)據(jù)的正確性。


          Application Data





          之后就是真正加密的數(shù)據(jù)了。


          總結(jié)



          我們?nèi)サ艨蛻舳俗C書這個部分,整個過程簡化來說一遍。
          1. client --> server ClientHello
          客戶端生成隨機數(shù),并發(fā)送一組密碼學套件供服務端選
          2. server--> client ServerHello
          服務端生成隨機數(shù),并從上述密碼學套件組里選一個
          3. server--> client Certificate
          服務端發(fā)給客戶端證書
          4. server--> client ServerKeyExchange
          服務端發(fā)給客戶端秘鑰交換算法所需的值
          5. server--> client ServerHelloDone
          服務端 hello 階段結(jié)束
          6. client --> server ClientKeyExchange
          戶端發(fā)給服務端秘鑰交換算法所需的
          7. client --> server ChangeCipherSpec
          客戶端告訴服務端,我已經(jīng)知道秘鑰了,之后的消息我就都加密發(fā)送了。
          8. client --> server Finish
          結(jié)束并驗證
          7. server --> server ChangeCipherSpec
          服務端告訴客戶端,我已經(jīng)知道秘鑰了,之后的消息我就都加密發(fā)送了。
          9. server--> client Finish

          結(jié)束并驗證

          如果不看客戶端證書,不看復雜的 premaster_secret 協(xié)商算法,不看壓縮算法這些細節(jié),其實簡單說只有三大步驟。
          首先第一步,客戶端對服務端說 hello,并且發(fā)一組密碼套件。
          第二步,服務端對客戶端說 hello,并且選擇一組密碼套件,同時把附帶公鑰的證書發(fā)給客戶端。
          第三步,客戶端驗證證書,并且把對稱加密的秘鑰用服務端的公鑰加密,發(fā)給服務端,服務端用私鑰解密出就是對稱加密秘鑰了。(當然實際情況沒這么簡單,比如我們本次抓包是用 ECDHE 秘鑰交換算法,這也是目前大部分網(wǎng)站的做法)。
          經(jīng)此三步之后,客戶端與服務端就都擁有了相同的對稱加密秘鑰,進行簡單的收尾工作,也就是通知對方秘鑰已生成好的信息,之后就可以開始通信了。
          最后說一句,本案例的抓包數(shù)據(jù)可以加我好友,朋友圈有下載鏈接,當然你也可以自己用 wireshark 抓,隨便訪問一個網(wǎng)站幾乎都是 https 的。

          參考資料:

          RFC-5246 The Transport Layer Security (TLS) Protocol Version 1.2

          RFC-1422 Privacy Enhancement for Internet Electronic Mail Part II: Certificate-Based Key Management


          瀏覽 52
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  天堂网www.资源在线 | 久久一级精品视频 | 亚洲天天干 | aa在线播放 | 日韩 中文 欧美 |