本文大部分整理自網絡,相關文章請見文後參考。
ssl/tls作為一種網際網路安全加密技術,原理較為複雜,枯燥而無味,我也是試圖了解之後重新整理,盡量做到層次清晰。正文開始。
ssl是一個介于http協定與tcp之間的一個可選層,其位置大緻如下:
ssl:(secure socket layer,安全套接字層),為netscape所研發,用以保障在internet上資料傳輸之安全,利用資料加密(encryption)技術,可確定資料在網絡上之傳輸過程中不會被截取。目前版本為3.0。它已被廣泛地用于web浏覽器與伺服器之間的身份認證和加密資料傳輸。
ssl協定位于tcp/ip協定與各種應用層協定之間,為資料通訊提供安全支援。ssl協定可分為兩層: ssl記錄協定(ssl record protocol):它建立在可靠的傳輸協定(如tcp)之上,為高層協定提供資料封裝、壓縮、加密等基本功能的支援。 ssl握手協定(ssl handshake protocol):它建立在ssl記錄協定之上,用于在實際的資料傳輸開始前,通訊雙方進行身份認證、協商加密算法、交換加密密鑰等。
tls:(transport layer security,傳輸層安全協定),用于兩個應用程式之間提供保密性和資料完整性。
ssl/tls協定提供的服務主要有:
認證使用者和伺服器,確定資料發送到正确的客戶機和伺服器;
加密資料以防止資料中途被竊取;
維護資料的完整性,確定資料在傳輸過程中不被改變。
版本号:tls記錄格式與ssl記錄格式相同,但版本号的值不同,tls的版本1.0使用的版本号為sslv3.1。
封包驗證碼:sslv3.0和tls的mac算法及mac計算的範圍不同。tls使用了rfc-2104定義的hmac算法。sslv3.0使用了相似的算法,兩者差别在于sslv3.0中,填充位元組與密鑰之間采用的是連接配接運算,而hmac算法采用的是異或運算。但是兩者的安全程度是相同的。
僞随機函數:tls使用了稱為prf的僞随機函數來将密鑰擴充成資料塊,是更安全的方式。
報警代碼:tls支援幾乎所有的sslv3.0報警代碼,而且tls還補充定義了很多報警代碼,如解密失敗(decryption_failed)、記錄溢出(record_overflow)、未知ca(unknown_ca)、拒絕通路(access_denied)等。
密文族和客戶證書:sslv3.0和tls存在少量差别,即tls不支援fortezza密鑰交換、加密算法和客戶證書。
certificate_verify和finished消息:sslv3.0和tls在用certificate_verify和finished消息計算md5和sha-1散列碼時,計算的輸入有少許差别,但安全性相當。
加密計算:tls與sslv3.0在計算主密值(master secret)時采用的方式不同。
填充:使用者資料加密之前需要增加的填充位元組。在ssl中,填充後的資料長度要達到密文塊長度的最小整數倍。而在tls中,填充後的資料長度可以是密文塊長度的任意整數倍(但填充的最大長度為255位元組),這種方式可以防止基于對封包長度進行分析的攻擊。
tls的主要增強内容
tls的主要目标是使ssl更安全,并使協定的規範更精确和完善。tls 在ssl v3.0 的基礎上,提供了以下增強内容:
更安全的mac算法
更嚴密的警報
“灰色區域”規範的更明确的定義
tls對于安全性的改進
對于消息認證使用密鑰散列法:tls 使用“消息認證代碼的密鑰散列法”(hmac),當記錄在開放的網絡(如網際網路)上傳送時,該代碼確定記錄不會被變更。sslv3.0還提供鍵控消息認證,但hmac比sslv3.0使用的(消息認證代碼)mac 功能更安全。
增強的僞随機功能(prf):prf生成密鑰資料。在tls中,hmac定義prf。prf使用兩種雜湊演算法保證其安全性。如果任一算法暴露了,隻要第二種算法未暴露,則資料仍然是安全的。
改進的已完成消息驗證:tls和sslv3.0都對兩個端點提供已完成的消息,該消息認證交換的消息沒有被變更。然而,tls将此已完成消息基于prf和hmac值之上,這也比sslv3.0更安全。
一緻證書處理:與sslv3.0不同,tls試圖指定必須在tls之間實作交換的證書類型。
特定警報消息:tls提供更多的特定和附加警報,以訓示任一會話端點檢測到的問題。tls還對何時應該發送某些警報進行記錄。
ssl協定分為兩部分:handshake protocol和record protocol。其中handshake protocol用來協商密鑰,協定的大部分内容就是通信雙方如何利用它來安全的協商出一份密鑰。 record protocol則定義了傳輸的格式。
由于非對稱加密的速度比較慢,是以它一般用于密鑰交換,雙方通過公鑰算法協商出一份密鑰,然後通過對稱加密來通信,當然,為了保證資料的完整性,在加密前要先經過hmac的處理。
ssl預設隻進行server端的認證,用戶端的認證是可選的。以下是其流程圖(摘自tls協定)。
由于用戶端(如浏覽器)對一些加解密算法的支援程度不一樣,但是在tls協定傳輸過程中必須使用同一套加解密算法才能保證資料能夠正常的加解密。在tls握手階段,用戶端首先要告知服務端,自己支援哪些加密算法,是以用戶端需要将本地支援的加密套件(cipher suite)的清單傳送給服務端。除此之外,用戶端還要産生一個随機數,這個随機數一方面需要在用戶端儲存,另一方面需要傳送給服務端,用戶端的随機數需要跟服務端産生的随機數結合起來産生後面要講到的 master secret 。
綜上,在這一步,用戶端主要向伺服器提供以下資訊:
支援的協定版本,比如tls 1.0版
一個用戶端生成的随機數,稍後用于生成"對話密鑰"
支援的加密方法,比如rsa公鑰加密
支援的壓縮方法
上圖中,從server hello到server done,有些服務端的實作是每條單獨發送,有服務端實作是合并到一起發送。sever hello和server done都是隻有頭沒有内容的資料。
服務端在接收到用戶端的client hello之後,服務端需要将自己的證書發送給用戶端。這個證書是對于服務端的一種認證。例如,用戶端收到了一個來自于稱自己是www.alipay.com的資料,但是如何證明對方是合法的alipay支付寶呢?這就是證書的作用,支付寶的證書可以證明它是alipay,而不是财付通。證書是需要申請,并由專門的數字證書認證機構(ca)通過非常嚴格的稽核之後頒發的電子證書。頒發證書的同時會産生一個私鑰和公鑰。私鑰由服務端自己儲存,不可洩漏。公鑰則是附帶在證書的資訊中,可以公開的。證書本身也附帶一個證書電子簽名,這個簽名用來驗證證書的完整性和真實性,可以防止證書被串改。另外,證書還有個有效期。
在服務端向用戶端發送的證書中沒有提供足夠的資訊(證書公鑰)的時候,還可以向用戶端發送一個 server key exchange,
此外,對于非常重要的保密資料,服務端還需要對用戶端進行驗證,以保證資料傳送給了安全的合法的用戶端。服務端可以向用戶端發出 cerficate request 消息,要求用戶端發送證書對用戶端的合法性進行驗證。比如,金融機構往往隻允許認證客戶連入自己的網絡,就會向正式客戶提供usb密鑰,裡面就包含了一張用戶端證書。
跟用戶端一樣,服務端也需要産生一個随機數發送給用戶端。用戶端和服務端都需要使用這兩個随機數來産生master secret。
最後服務端會發送一個server hello done消息給用戶端,表示server hello消息結束了。
綜上,在這一步,伺服器的回應包含以下内容:
确認使用的加密通信協定版本,比如tls 1.0版本。如果浏覽器與伺服器支援的版本不一緻,伺服器關閉加密通信
一個伺服器生成的随機數,稍後用于生成"對話密鑰"
确認使用的加密方法,比如rsa公鑰加密
伺服器證書
client key exchange
如果服務端需要對用戶端進行驗證,在用戶端收到服務端的 server hello 消息之後,首先需要向服務端發送用戶端的證書,讓服務端來驗證用戶端的合法性。
certificate verify
接着,用戶端需要對服務端的證書進行檢查,如果證書不是可信機構頒布、或者證書中的域名與實際域名不一緻、或者證書已經過期,就會向通路者顯示一個警告,由其選擇是否還要繼續通信。如果證書沒有問題,用戶端就會從伺服器證書中取出伺服器的公鑰。然後,向伺服器發送下面三項資訊:
一個随機數。該随機數用伺服器公鑰加密,防止被竊聽
編碼改變通知,表示随後的資訊都将用雙方商定的加密方法和密鑰發送
用戶端握手結束通知,表示用戶端的握手階段已經結束。這一項同時也是前面發送的所有内容的hash值,用來供伺服器校驗
上面第一項的随機數,是整個握手階段出現的第三個随機數,它是用戶端使用一些加密算法(例如:rsa, diffie-hellman)産生一個48個位元組的key,這個key叫 premaster secret,很多材料上也被稱作 premaster key。
changecipherspec
changecipherspec是一個獨立的協定,展現在資料包中就是一個位元組的資料,用于告知服務端,用戶端已經切換到之前協商好的加密套件(cipher suite)的狀态,準備使用之前協商好的加密套件加密資料并傳輸了。
在changecipherspec傳輸完畢之後,用戶端會使用之前協商好的加密套件和session secret加密一段 finish 的資料傳送給服務端,此資料是為了在正式傳輸應用資料之前對剛剛握手建立起來的加解密通道進行驗證。
服務端在接收到用戶端傳過來的 premaster 加密資料之後,使用私鑰對這段加密資料進行解密,并對資料進行驗證,也會使用跟用戶端同樣的方式生成 session secret,一切準備好之後,會給用戶端發送一個 changecipherspec,告知用戶端已經切換到協商過的加密套件狀态,準備使用加密套件和 session secret加密資料了。之後,服務端也會使用 session secret 加密一段 finish 消息發送給用戶端,以驗證之前通過握手建立起來的加解密通道是否成功。
根據之前的握手資訊,如果用戶端和服務端都能對finish資訊進行正常加解密且消息正确的被驗證,則說明握手通道已經建立成功,接下來,雙方可以使用上面産生的session secret對資料進行加密傳輸了。
secret keys
上面的分析和講解主要是為了突出握手的過程,是以premaster secret,master secret,session secret都是一代而過,但是對于https,ssl/tls深入的了解和掌握,這些secret keys是非常重要的部分。是以,準備把這些secret keys抽出來單獨分析和講解。
我們先來看看這些secret keys的生成過程以及作用流程圖:
premaster secret
premaster secret是在用戶端使用rsa或者diffie-hellman等加密算法生成的。它将用來跟服務端和用戶端在hello階段産生的随機數結合在一起生成 master secret。在用戶端使用服務端的公鑰對premaster secret進行加密之後傳送給服務端,服務端将使用私鑰進行解密得到premaster secret。也就是說服務端和用戶端都有一份相同的premaster secret和随機數。
premaster secret前兩個位元組是tls的版本号,這是一個比較重要的用來核對握手資料的版本号,因為在client hello階段,用戶端會發送一份加密套件清單和目前支援的ssl/tls的版本号給服務端,而且是使用明文傳送的,如果握手的資料包被破解之後,攻擊者很有可能串改資料包,選擇一個安全性較低的加密套件和版本給服務端,進而對資料進行破解。是以,服務端需要對密文中解密出來對的premaster版本号跟之前client hello階段的版本号進行對比,如果版本号變低,則說明被串改,則立即停止發送任何消息。
master secret
上面已經提到,由于服務端和用戶端都有一份相同的premaster secret和随機數,這個随機數将作為後面産生master secret的種子,結合premaster secret,用戶端和服務端将計算出同樣的master secret。
master secret是有系列的hash值組成的,它将作為資料加解密相關的secret的 key material 的一部分。key material最終解析出來的資料如下:
其中,write mac key,就是session secret或者說是session key。client write mac key是用戶端發資料的session secret,server write mac secret是服務端發送資料的session key。mac(message authentication code),是一個數字簽名,用來驗證資料的完整性,可以檢測到資料是否被串改。
在所有的握手階段都完成之後,就可以開始傳送應用資料了。應用資料在傳輸之前,首先要附加上mac secret,然後再對這個資料包使用write encryption key進行加密。在服務端收到密文之後,使用client write encryption key進行解密,用戶端收到服務端的資料之後使用server write encryption key進行解密,然後使用各自的write mac key對資料的完整性包括是否被串改進行驗證。
ssl用戶端(也是tcp的用戶端)在tcp連結建立之後,發出一個clienthello來發起握手,這個消息裡面包含了自己可實作的算法清單和其它一些需要的消息,ssl的伺服器端會回應一個serverhello,這裡面确定了這次通信所需要的算法,然後發過去自己的證書(裡面包含了身份和自己的公鑰)。client在收到這個消息後會生成一個秘密消息,用ssl伺服器的公鑰加密後傳過去,ssl伺服器端用自己的私鑰解密後,會話密鑰協商成功,雙方可以用同一份會話密鑰來通信了。
如果上面的說明不夠清晰,這裡我們用個形象的比喻,我們假設a與b通信,a是ssl用戶端,b是ssl伺服器端,加密後的消息放在方括号[]裡,以突出明文消息的差別。雙方的處理動作的說明用圓括号()括起。
a:我想和你安全的通話,我這裡的對稱加密算法有des,rc5,密鑰交換算法有rsa和dh,摘要算法有md5和sha。
b:我們用des-rsa-sha這對組合好了。
這是我的證書,裡面有我的名字和公鑰,你拿去驗證一下我的身份(把證書發給a)。
目前沒有别的可說的了。
a:(檢視證書上b的名字是否無誤,并通過手頭早已有的ca的證書驗證了b的證書的真實性,如果其中一項有誤,發出警告并斷開連接配接,這一步保證了b的公鑰的真實性)
(産生一份秘密消息,這份秘密消息處理後将用作加密密鑰,加密初始化向量(iv)和hmac的密鑰。将這份秘密消息-協定中稱為per_master_secret-用b的公鑰加密,封裝成稱作clientkeyexchange的消息。由于用了b的公鑰,保證了第三方無法竊聽)
我生成了一份秘密消息,并用你的公鑰加密了,給你(把clientkeyexchange發給b)
注意,下面我就要用加密的辦法給你發消息了!
(将秘密消息進行處理,生成加密密鑰,加密初始化向量和hmac的密鑰)
[我說完了]
b:(用自己的私鑰将clientkeyexchange中的秘密消息解密出來,然後将秘密消息進行處理,生成加密密鑰,加密初始化向量和hmac的密鑰,這時雙方已經安全的協商出一套加密辦法了)
注意,我也要開始用加密的辦法給你發消息了!
a: [我的秘密是...]
b: [其它人不會聽到的...]
從上面的原理可知,ssl的結構是嚴謹的,問題一般出現在實際不嚴謹的應用中。常見的攻擊就是middle in the middle攻擊,它是指在a和b通信的同時,有第三方c處于信道的中間,可以完全聽到a與b通信的消息,并可攔截,替換和添加這些消息。
ssl可以允許多種密鑰交換算法,而有些算法,如dh,沒有證書的概念,這樣a便無法驗證b的公鑰和身份的真實性,進而c可以輕易的冒充,用自己的密鑰與雙方通信,進而竊聽到别人談話的内容。
而為了防止middle in the middle攻擊,應該采用有證書的密鑰交換算法。
有了證書以後,如果c用自己的證書替換掉原有的證書之後,a的浏覽器會彈出一個警告框進行警告,但又有多少人會注意這個警告呢?
由于美國密碼出口的限制,ie,netscape等浏覽器所支援的加密強度是很弱的,如果隻采用浏覽器自帶的加密功能的話,理論上存在被破解可能。
下面探讨一下ssl的代理是怎樣工作的
當在浏覽器裡設定了https的代理,而且裡輸入了<code>https://www.example.com</code>之後,浏覽器會與proxy建立tcp連結,然後向其發出這麼一段消息:
然後proxy會向webserver端建立tcp連接配接,之後,這個代理便完全成了個内容轉發裝置。浏覽器與web server會建立一個安全通道,是以這個安全通道是端到端的,盡管所有的資訊流過了proxy,但其内容proxy是無法解密和改動的(當然要由證書的支援,否則這個地友善是個man in the middle攻擊的好場所,見上面的安全部分)。