摘要:另一方比如小明得到公鑰之后,雙方就可以通信。然而,中間人還是可能截獲公鑰,然后自己弄一對秘鑰,然后告訴小明說是小紅的公鑰。這樣,小亮在簽署小紅的身份證的時候,可以在小紅身份證后面附上自己的身份證。一般來說,自簽名的根身份證用于公司內(nèi)部使用。
前言
自從 Let"s Encrypt 上線之后,HTTPS 網(wǎng)站數(shù)量占比越來越高,相信不久的未來就可以實(shí)現(xiàn)全網(wǎng) HTTPS,大部分主流瀏覽器也對 HTTP 網(wǎng)頁給出明顯的 不安全 標(biāo)志。
SSL 是在 TCP 層之上為客戶端服務(wù)端之間數(shù)據(jù)傳輸運(yùn)用復(fù)雜的加密算法,swoole 使用 SSL 加密只需要兩個步驟:
$serv = new swoole_server("0.0.0.0", 443, SWOOLE_PROCESS, SWOOLE_SOCK_TCP | SWOOLE_SSL); $key_dir = dirname(dirname(__DIR__))."/tests/ssl"; $serv->set(array( "worker_num" => 4, "ssl_cert_file" => $key_dir."/ssl.crt", "ssl_key_file" => $key_dir."/ssl.key", ));SSL/TLS 安全通信
由于 HTTPS 的推出受到了很多人的歡迎,在 SSL 更新到 3.0 時,IETF 對 SSL3.0 進(jìn)行了標(biāo)準(zhǔn)化,并添加了少數(shù)機(jī)制(但是幾乎和 SSL3.0 無差異),標(biāo)準(zhǔn)化后的 IETF 更名為 TLS1.0 (Transport Layer Security 安全傳輸層協(xié)議),可以說 TLS 就是 SSL 的新版本 3.1,并同時發(fā)布“ RFC2246-TLS 加密協(xié)議詳解”。
首先我們先來了解一下 SSL/TLS 的原理。
以下內(nèi)容來源于參考文獻(xiàn):TLS和安全通信
加密技術(shù)TLS 依賴兩種加密技術(shù):
對稱加密(symmetric encryption)
非對稱加密(asymmetric encryption)
對稱加密對稱加密的一方(比如小紅)用秘鑰 K 給文本 M 加密;另一方(比如小明)用
同一個秘鑰解密:
小紅 : C = E(M, K) 小明 : M = D(C, K)
這有一個問題:當(dāng)一方生成了秘鑰 K 之后得把 K 分享給另一方。但是穿越 `Sin
City 的道路危險(xiǎn)中途很可能有人竊聽到 K`,竊聽者就可以假扮雙方中的任何一
方與另一方通信。這叫中間人攻擊。
非對稱加密利用成對的兩個秘鑰:K1 和 K2。小紅用其中一個加密文本,小明可
以用另一個解密文本。比如,小紅用 K1 加密,小明用 K2 解密:
小紅 : C = E(M, K1) 小明 : M = D(C, K2)
這樣一來,雙方中的一方(比如小紅)可以生成 K1 和 K2,然后把其中一個秘鑰(比如 K1)私藏,稱為私鑰;另一個(比如K2)公開,稱為公鑰。另一方(比如小明)得到公鑰之后,雙方就可以通信。
然而,中間人還是可能截獲公鑰 K2,然后自己弄一對秘鑰(κ1, κ2),然后告訴小明說 κ2 是小紅的公鑰。這樣中間人每次可以用截獲的 K2 解密小紅發(fā)給小明的文本(甚至可能修改文本),再用 κ1 加密了發(fā)出去;小明用 κ2 解密接收。
數(shù)字簽名和CA為了幫小明確定得到的公鑰確實(shí)是小紅的 K2,而不是中間人偽造的 κ2,牛人們發(fā)明了數(shù)字簽名(digital signature)技術(shù)。
數(shù)字簽名的做法是:
小紅把自己的公鑰和 ID(身份證號碼,或者域名)合為身份證申請(certificate signing request,CSR),
小紅把 CSR 發(fā)給一個德高望重的人(被稱為 certificate authority,CA),比如小亮,
小亮用自己的私鑰加密小紅的 CSR,得到的密文被稱為數(shù)字簽名(digital signature),
小亮把 signature 和 CSR 的明文合在一起稱為 CA簽署的身份證(CA signed certificate,CRT),發(fā)給小紅,
小紅:CSR = 小紅公鑰+小紅域名 signature = E(CSR, 小亮的私鑰) CRT = CSR + signature
每當(dāng)其他人(比如小明)找小紅聊天(建立 HTTPS 連接)的時候,小紅出示自己的小亮簽署的身份證。拿到這個身份證的人,只要他是相信小亮的——在自己機(jī)器上安裝了小亮的身份證,就可以
從小亮的身份證中的小亮的 CSR 里提取小亮的公鑰;
然后用小亮的公鑰解密小紅的身份證中小亮的 signature,得到一個小紅的 CSR;
如果這個 CSR 和小紅身份證中的 CSR 明文一致,則說明“這個小紅的身份證是小亮確認(rèn)過并且簽名的”。
小明:小亮的公鑰 = 小亮的CRT.CSR.小亮的公鑰 CSR" = D(CRT.signature, 小亮的公鑰) if CSR" == CRT.CSR then OK
由此過程可以看出來:隨便誰都可以當(dāng) CA ——只要愿意公開自己的公鑰,即可用自己的私鑰去加密別人的認(rèn)證。那我們要是信錯了 CA,被他擺一道怎么辦?答案是:沒辦法。我們選擇信任社會,要相信如果 CA 說謊,萬一被識破,就沒有人
再相信他了?,F(xiàn)實(shí)中,很多操作系統(tǒng)(Windows、Mac OS X)和瀏覽器(Chrome、Firefox、IE)會內(nèi)置一些靠譜的 CA 的身份證。
小亮如果擔(dān)心沒有人信任自己是個好 CA(就像沒人信CNNIC一樣),可以找一個大家都信的 CA,比如老王,用老王的私鑰在小亮的身份證上簽名:
小亮:CSR = 小亮的公鑰+小亮域名 signature = E(CSR, 老王的私鑰) CRT = CSR + signature
如果瀏覽器或者操作系統(tǒng)里安裝了老王的公鑰則可以驗(yàn)證“小亮的身份證是老王確認(rèn)并且簽名過的”。
這樣,小亮在簽署小紅的身份證的時候,可以在小紅身份證后面附上自己的身份證。這樣小紅的身份證就有“兩頁”了。
當(dāng)小明和小紅通信的時候:
小明會先要求小紅出示自己的身份證;
小明雖然不信任小亮,但是信任老王,所以小明可以用老王的身份證里的老
王的公鑰來驗(yàn)證小紅身份證附帶的小亮的身份證,于是就可以信任小亮了;
然后小明用小亮身份證里的公鑰驗(yàn)證小紅的身份證。
要是怕小明連自己也也不信任,老王可以再找一個小明信任的人來簽名確認(rèn)自己的身份證。這個過程可以不斷遞推,從而形成了一條信任鏈(trust of chain)
根身份證和自簽名信任鏈總會有個頂端,被稱為根身份證(root CA)。那么根身份證是誰簽名的呢?答案是:自己簽名。實(shí)際上,我們每個人都可以自己簽名認(rèn)證自己的身份證,得到自簽名的身份證(self-signed certificate)。具體過程是:
生成一對秘鑰:公鑰 K2 和私鑰 K1,
創(chuàng)建自己的 CSR,
用自己的秘鑰加密 CSR 得到 signature,然后把 CSR 明文和 signature 一起發(fā)布。
任何人只要信任我們自簽名的身份證 CRT,也就可以用 CRT.CSR.K2 作為公鑰加密要傳遞給我們的文本。我們可以用自己的私鑰 K1 來解密文本。
一般來說,自簽名的根身份證用于公司內(nèi)部使用。
如果老王就是根 CA 了,那么上述各位的身份證的信任鏈如下:
小紅:CSR = 小紅公鑰+小紅域名 signature = E(CSR, 小亮的私鑰) CRT = CSR + signature 小亮:CSR = 小亮的公鑰+小亮域名 signature = E(小亮的CSR, 老王的私鑰) CRT = 小亮的CSR + signature 老王:CSR = 老王的公鑰+老王的域名 signature = E(老王的CSR, 老王自己的私鑰) CRT = 老王的CSR + signature雙方TLS認(rèn)證
上述例子解釋了通信的一方如何驗(yàn)證另一方的身份。這種情況的一個常見應(yīng)用是:我們通過瀏覽器訪問銀行的網(wǎng)頁。這里的關(guān)鍵是,我們要能驗(yàn)證銀行的身份證,然后才敢于在網(wǎng)頁里輸入賬號和密碼。瀏覽器驗(yàn)證銀行的身份證的過程如下:
在瀏覽器和銀行的HTTPS服務(wù)建立安全連接的過程中,銀行的HTTPS服務(wù)會把
它的身份證發(fā)給瀏覽器
瀏覽器使用內(nèi)置的CA的身份證來驗(yàn)證銀行的身份證。
瀏覽器驗(yàn)證了銀行的 HTTPS 服務(wù)的身份之后,就輪到銀行驗(yàn)證瀏覽器的用戶的身份了:
瀏覽器展示銀行HTTPS服務(wù)發(fā)來的登陸頁面;
用戶在這個頁面里輸入賬號和密碼,銀行的HTTPS服務(wù)由此驗(yàn)證用戶的身份。
在這個過程中,銀行 HTTPS 服務(wù)器的身份是通過 TLS 身份證來驗(yàn)證的。而我們(用戶)的身份是通過我們輸入的賬號和密碼來驗(yàn)證的。
有時通信的雙方都是程序(而不是人)。此時,讓一方輸入賬號和密碼,不如讓雙方都通過 TLS 身份證來互相驗(yàn)證方便。尤其是在很多分布式系統(tǒng)里,有多種類型的程序互相通信,而不只是兩方通信。
比如在 Kubernetes 機(jī)群里,不光操作機(jī)群的客戶端程序 kubectl 要能驗(yàn)證 Kubernetes master node(具體的說是 apiserver)的身份,才能放心地把包括敏感信息(比如數(shù)據(jù)庫密碼)的計(jì)算作業(yè)提交給 apiserver。類似的,apiserver 也要能驗(yàn)證 kubectl 的身份,以確認(rèn)提交作業(yè)的是公司的合法雇員,而不是外賊。
為此,通信各方都需要有各自的身份證。一個公司可以自簽名一個 CA 身份證,并且用它來給每個雇員以及每個程序簽署身份證。這樣,只要每臺電腦上都預(yù)先安裝好公司自己的 CA 身份證,就可以用這個身份證驗(yàn)證每個雇員和程序的身份了。
這是目前很多公司的常用做法。
因?yàn)?TLS 模式下所有傳輸?shù)臄?shù)據(jù)都是加密的,大家會關(guān)注加密和解密的性能。客觀的說,非對稱加密技術(shù)的加密和解密比較慢,相對來說,對稱加密技術(shù)的加密解密過程更快。所以實(shí)際的連接和握手過程中,通信雙方會協(xié)商一個對稱加密秘鑰,之后的數(shù)據(jù)通信過程中的加密都是利用對稱加密技術(shù)來實(shí)現(xiàn)的。
具體的做法是:握手的時候,雙方各自生成一個隨機(jī)數(shù),并且以非對稱加密的方式分享給對方。然后每一方都把自己的隨機(jī)數(shù)和對方的隨機(jī)數(shù)拼起來,就是接下來通信時候使用的對稱加密方法的秘鑰了。
OpenSSL 操作指南接下來,我們來看看如何生成 HTTPS 所需要的證書。
以下內(nèi)容來源于參考文獻(xiàn):openssl的介紹和使用
openssl 簡介OpenSSL 是一個開源項(xiàng)目,其組成主要包括一下三個組件:
openssl:多用途的命令行工具
libcrypto:加密算法庫
libssl:加密模塊應(yīng)用庫,實(shí)現(xiàn)了ssl及tls
openssl 可以實(shí)現(xiàn):秘鑰證書管理、對稱加密和非對稱加密更多簡介和官網(wǎng)。
指令平時我們使用 openssl 最多的莫過于使用指令了,而最為常見的幾個指令如下:
genrsa 生成RSA參數(shù)
req
x509
rsa
ca
genrsa 簡介平時主要用來生成私鑰,選擇使用的算法、對稱加密密碼和私鑰長度來生成私鑰。也就是生成 key 文件。
基本用法:
openssl genrsa [args] [numbits]
其中常見的參數(shù):【更多參數(shù)查看:openssl genrsa -help】
args1 對生成的私鑰文件是否要使用加密算法進(jìn)行對稱加密: -des : CBC模式的DES加密 -des3 : CBC模式的3DES加密 -aes128 : CBC模式的AES128加密 -aes192 : CBC模式的AES192加密 -aes256 : CBC模式的AES256加密 args2 對稱加密密碼 -passout passwords 其中passwords為對稱加密(des、3des、aes)的密碼(使用這個參數(shù)就省去了console交互提示輸入密碼的環(huán)節(jié)) args3 輸出文件 -out file : 輸出證書私鑰文件 [numbits]: 密鑰長度,理解為私鑰長度
生成一個 2048 位的 RSA 私鑰,并用 des3 加密(密碼為 123456 ),保存為 server.key 文件
openssl genrsa -des3 -passout pass:123456 -out server.key 2048 // -des3 是第一個參數(shù)args1; // -passout pass:123456 是第二個參數(shù)寫法 args2 // -out server.key 第三個參數(shù)args3; // 2048 最后一個[numbits]參數(shù)
生成的 key 文件是 PEM 格式的
-----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: DES-EDE3-CBC,DB98A9512DD7CBCF yKTM+eoxBvptGrkEixhljqHSuE+ucTh3VqYQsgO6+8Wbh1docbFUKzLKHrferJBH ... -----END RSA PRIVATE KEY-----
雖說文件頭尾都標(biāo)注著 RSA PRIVATE KEY,但實(shí)際上這個文件里既包括公鑰也包括私鑰。
req 命令req 的基本功能主要有兩個:生成證書請求和生成自簽名證書,也就是 csr 文件,或者自簽名的 crt 文件。當(dāng)然這并不是其全部功能,但是這兩個最為常見;
常見使用方法:
openssl req [args] outfile
主要參數(shù):【更多參數(shù)查看:openssl req -help】
args1 是輸入輸入文件格式: -inform arg -inform DER 使用輸入文件格式為DER -inform PEM 使用輸入文件格式為PEM args2 輸出文件格式: -outform arg -outform DER 使用輸出文件格式為DER -outform PEM 使用輸出文件格式為PEM args3 是待處理文件 -in inputfilepath args4 待輸出文件 -out outputfilepath args5 用于簽名待生成的請求證書的私鑰文件的解密密碼 -passin passwords args6 用于簽名待生成的請求證書的私鑰文件 -key file args7 指定輸入密鑰的編碼格式 -keyform arg -keyform DER -keyform NET -keyform PEM args8 生成新的證書請求 -new args9 輸出一個X509格式的證書,簽名證書時使用 -x509 args10 使用 X509 簽名證書的有效時間 -days // -days 3650 有效期10年 args11 生成一個bits長度的RSA私鑰文件,用于簽發(fā)【生成私鑰、并生成自簽名證書】 -newkey rsa:bits args12設(shè)置HASH算法-[digest]【生成私鑰指定的hash摘要算法】 -md5 -sha1 // 高版本瀏覽器開始不信任這種算法 -md2 -mdc2 -md4 args13指定openssl配置文件,很多內(nèi)容不容易通過參數(shù)配置,可以指定配置文件 -config filepath args14 顯示格式txt【用于查看證書、私鑰信息】 -text
使用的案例:利用私鑰生成證書請求 csr
openssl req -new -key server.key -out server.csr
server.csr 文件也是 PEM 格式的,文件頭尾標(biāo)注為 CERTIFICATE REQUEST:
-----BEGIN CERTIFICATE REQUEST----- MIIC0TCCAbkCAQAwgYsxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTERMA8GA1UE ... -----END CERTIFICATE REQUEST-----
使用案例:利用私鑰生成自簽名證書
openssl req -new -x509 -days 3650 -key ca.key -out ca.crtx509 命令
x509 是一個功能很豐富的證書處理工具。可以用來顯示證書的內(nèi)容,轉(zhuǎn)換其格式,給 CSR 簽名等 X.509 證書的管理工作;
用法如下:
openssl x509 [args]
參數(shù)如下:【更多參數(shù)查看:openssl x509 -help】
args1 是輸入輸入文件格式: -inform arg -inform DER 使用輸入文件格式為DER -inform PEM 使用輸入文件格式為PEM args2 輸出文件格式: -outform arg -outform DER 使用輸出文件格式為DER -outform PEM 使用輸出文件格式為PEM args3 是待處理X509證書文件 -in inputfilepath args4 待輸出X509證書文件 -out outputfilepath args5表明輸入文件是一個"請求簽發(fā)證書文件(CSR)",等待進(jìn)行簽發(fā) -req args6簽名證書的有效時間 -days // -days 3650 有效期10年 args7 指定用于簽發(fā)請求證書的根CA證書 -CA arg args8 根CA證書格式(默認(rèn)是PEM) -CAform arg args9 指定用于簽發(fā)請求證書的CA私鑰證書文件 -CAkey arg args10 指定根CA私鑰證書文件格式(默認(rèn)為PEM格式) -CAkeyform arg args11 指定序列號文件(serial number file) -CAserial arg args12 如果序列號文件(serial number file)沒有指定,則自動創(chuàng)建它 -CAcreateserial args13設(shè)置HASH算法-[digest]【生成私鑰指定的hash摘要算法】 -md5 -sha1 // 高版本瀏覽器開始不信任這種算法 -md2 -mdc2 -md4
使用實(shí)例: 使用根 CA 證書[ ca.crt ]和私鑰[ ca.key ]對"請求簽發(fā)證書"[ server.csr ]進(jìn)行簽發(fā),生成 x509 格式證書
openssl x509 -req -days 3650 -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out serverx509.crt
server.crt 也是 PEM 格式的。文件頭尾的標(biāo)記為 CERTIFICATE:
-----BEGIN CERTIFICATE----- MIIDlDCCAnwCCQDQ1UvQyFD7jDANBgkqhkiG9w0BAQsFADCBizELMAkGA1UEBhMC ... -----END CERTIFICATE-----DER、CRT、CER、PEM、KEY、PFX/P12 格式
下文參考文獻(xiàn):DER、CRT、CER、PEM格式的證書及轉(zhuǎn)換
證書和編碼X.509 證書,其核心是根據(jù) RFC 5280 編碼或數(shù)字簽名的數(shù)字文檔。
實(shí)際上,術(shù)語 X.509 證書通常指的是 IETF 的 PKIX 證書和 X.509 v3 證書標(biāo)準(zhǔn)的 CRL 文件,即如 RFC 5280(通常稱為PKIX for Public Key Infrastructure(X.509))中規(guī)定的。
X509文件擴(kuò)展我們首先要了解的是每種類型的文件擴(kuò)展名。 很多人不清楚DER,PEM,CRT和CER結(jié)尾的文件是什么,更有甚者錯誤地說是可以互換的。 在某些情況下,某些可以互換,最佳做法是識別證書的編碼方式,然后正確標(biāo)記。 正確標(biāo)簽的證書將更容易操縱
編碼--決定擴(kuò)展名方式 .DER 擴(kuò)展名.DER = DER 擴(kuò)展用于二進(jìn)制 DER 編碼證書。
這些文件也可能承載 CER 或 CRT 擴(kuò)展。 正確的說法是“我有一個 DER 編碼的證書”不是“我有一個 DER 證書”。
.PEM 擴(kuò)展名.PEM = PEM 擴(kuò)展用于不同類型的 X.509v3 文件,是以“ - BEGIN ...”前綴的 ASCII(Base64) 數(shù)據(jù)。
常見的擴(kuò)展.CRT 擴(kuò)展名
.CRT = CRT 擴(kuò)展用于證書。 證書可以被編碼為二進(jìn)制 DER 或 ASCII PEM。 CER 和 CRT 擴(kuò)展幾乎是同義詞。 最常見的于 Unix 或類 Unix 系統(tǒng)。
.CER 擴(kuò)展名
CER = .crt 的替代形式(Microsoft Convention)您可以在微軟系統(tǒng)環(huán)境下將 .crt 轉(zhuǎn)換為 .cer( .DER 編碼的 .cer,或 base64 [PEM] 編碼的 .cer)。
.KEY 擴(kuò)展名
.KEY = KEY 擴(kuò)展名用于公鑰和私鑰 PKCS#8。 鍵可以被編碼為二進(jìn)制 DER 或 ASCII PEM。
PFX/P12 擴(kuò)展名
predecessor of PKCS#12,對 *nix 服務(wù)器來說,一般 CRT 和 KEY 是分開存放在不同文件中的,但 Windows 的 IIS 則將它們存在一個 PFX 文件中,(因此這個文件包含了證書及私鑰)這樣會不會不安全?應(yīng)該不會,PFX 通常會有一個"提取密碼", 你想把里面的東西讀取出來的話,它就要求你提供提取密碼,PFX 使用的時 DER 編碼,如何把 PFX 轉(zhuǎn)換為 PEM 編碼?
openssl pkcs12 -in for-iis.pfx -out for-iis.pem -nodes
這個時候會提示你輸入提取代碼. for-iis.pem 就是可讀的文本.
生成 pfx 的命令類似這樣:
openssl pkcs12 -export -out certificate.pfx -inkey privateKey.key -in certificate.crt -certfile CACert.crt
其中 CACert.crt 是 CA (權(quán)威證書頒發(fā)機(jī)構(gòu))的根證書,有的話也通過 -certfile 參數(shù)一起帶進(jìn)去.這么看來,PFX 其實(shí)是個證書密鑰庫.
常見的 OpenSSL 證書操作證書操作有四種基本類型。查看,轉(zhuǎn)換,組合和提取。
查看證書即使PEM編碼的證書是 ASCII,它們也是不可讀的。這里有一些命令可以讓你以可讀的形式輸出證書的內(nèi)容;
查看 PEM 編碼證書
openssl x509 -in cert.pem -text –noout openssl x509 -in cert.cer -text –noout openssl x509 -in cert.crt -text –noout 如果您遇到這個錯誤,這意味著您正在嘗試查看DER編碼的證書,并需要使用“查看DER編碼證書”中的命令。 unable to load certificate 12626:error:0906D06C:PEMroutines:PEM_read_bio:no start line:pem_lib.c:647:Expecting: TRUSTEDCERTIFICATE
查看 DER 編碼證書
openssl x509 -in certificate.der -inform der -text -noout 如果您遇到以下錯誤,則表示您嘗試使用DER編碼證書的命令查看PEM編碼證書。在“查看PEM編碼的證書”中使用命令 unable to load certificate 13978:error:0D0680A8:asn1 encodingroutines:ASN1_CHECK_TLEN:wrong tag:tasn_dec.c:1306: 13978:error:0D07803A:asn1 encodingroutines:ASN1_ITEM_EX_D2I:nested asn1 error:tasn_dec.c:380:Type=X509轉(zhuǎn)換證書格式
轉(zhuǎn)換可以將一種類型的編碼證書存入另一種。(即PEM到DER轉(zhuǎn)換)
openssl x509 -in cert.crt -outform der-out cert.der openssl x509 -in cert.crt -inform der -outform pem -out cert.pem組合證書
在某些情況下,將多個 X.509 基礎(chǔ)設(shè)施組合到單個文件中是有利的。一個常見的例子是將私鑰和公鑰兩者結(jié)合到相同的證書中。
組合密鑰和鏈的最簡單的方法是將每個文件轉(zhuǎn)換為 PEM 編碼的證書,然后將每個文件的內(nèi)容簡單地復(fù)制到一個新文件中。這適用于組合文件以在 Apache 中使用的應(yīng)用程序
證書提取一些證書將以組合形式出現(xiàn)。 一個文件可以包含以下任何一個:證書,私鑰,公鑰,簽名證書,證書頒發(fā)機(jī)構(gòu)(CA)和/或權(quán)限鏈。
SSL/TLS 握手流程 簡潔版流程第一步,愛麗絲給出協(xié)議版本號、一個客戶端生成的隨機(jī)數(shù)(Client random),以及客戶端支持的加密方法。
第二步,鮑勃確認(rèn)雙方使用的加密方法,并給出數(shù)字證書、以及一個服務(wù)器生成的隨機(jī)數(shù)(Server random)。
第三步,愛麗絲確認(rèn)數(shù)字證書有效,然后生成一個新的隨機(jī)數(shù)(Premaster secret),并使用數(shù)字證書中的公鑰,加密這個隨機(jī)數(shù),發(fā)給鮑勃。
第四步,鮑勃使用自己的私鑰,獲取愛麗絲發(fā)來的隨機(jī)數(shù)(即 Premaster secret)。
第五步,愛麗絲和鮑勃根據(jù)約定的加密方法,使用前面的三個隨機(jī)數(shù),生成"對話密鑰"(session key),對話密鑰被切片生成兩個對稱密鑰和 MAC 密鑰,用來加密接下來的整個對話過程。
注意這個例子只是傳統(tǒng)的 RSA 模式密鑰交換的 SSL 握手流程。
詳細(xì)流程以下內(nèi)容參考文獻(xiàn):
SSL/TLS協(xié)議運(yùn)行機(jī)制的概述
SSL/TLS協(xié)議詳解
客戶端發(fā)出請求(ClientHello)握手第一步是客戶端向服務(wù)端發(fā)送 Client Hello 消息,這個消息里包含了
一個客戶端生成的隨機(jī)數(shù) Client random、
客戶端支持的加密套件(Support Ciphers)
支持的協(xié)議版本 SSL Version,比如TLS 1.0版。
支持的壓縮方法
Session id 用于會話復(fù)用
Extension 拓展字段的存在,是因?yàn)?SSL 協(xié)議起草之初有些功能沒有考慮到,后續(xù)這些功能被加進(jìn) RFC,而為了兼容 SSL,把這些功能的描述放到 Extension 中。
Server_name(SNI): 客戶端在 client hello 中帶上 server name 拓展(如果使用 ip 地址進(jìn)行訪問,那么就不會有 server name 拓展),它會捎帶上域名地址,服務(wù)器解析到 server name 后,就會根據(jù) server name 中的域名,選擇合適的證書。
Elliptic_curves/ec_point_formats: 使用橢圓曲線密鑰交換算法的時候用到,里面列舉了自己支持的橢圓曲線算法,供服務(wù)器選擇。
SessionTicket TLS: 會話復(fù)用時使用。
status_request: 請求 OCSP,服務(wù)器可以發(fā)送 cettificate status 到客戶端,里面帶上 ocsp 的信息。
signature_algorithms: 表示自己支持的簽名算法,服務(wù)器收到這個拓展,在進(jìn)行例如 server key exchange 簽名等操作時,需要參考客戶端這個拓展。
application_layer_negotiation(ALPN): 用以描述支持的上層協(xié)議,h2、http/1.1、spdy等??梢园阉胂蟪蒊P頭中的protocol,描述了上層是TCP還是UDP還是ICMP。目前主流瀏覽器,若要使用HTTP2,則必須使用這個拓展。
Renegotiation info: 如果是重新協(xié)商(即加密的 hello),那么會帶上上次協(xié)商的 12 字節(jié)的 finished,如果是新 hello 請求,那么里面字段為0。
切記及時服務(wù)器端不支持renegotiation,在server hello響應(yīng)時也需要帶上這個拓展
這里需要注意的是,客戶端發(fā)送的信息之中不包括服務(wù)器的域名。也就是說,理論上服務(wù)器只能包含一個網(wǎng)站,否則會分不清應(yīng)該向客戶端提供哪一個網(wǎng)站的數(shù)字證書。這就是為什么通常一臺服務(wù)器只能有一張數(shù)字證書的原因。
對于虛擬主機(jī)的用戶來說,這當(dāng)然很不方便。2006年,TLS協(xié)議加入了一個 Server Name Indication 擴(kuò)展,允許客戶端向服務(wù)器提供它所請求的域名。
服務(wù)器回應(yīng)(SeverHello)服務(wù)器收到客戶端請求后,向客戶端發(fā)出回應(yīng),這叫做SeverHello。服務(wù)器的回應(yīng)包含以下內(nèi)容。
確認(rèn)使用的加密通信協(xié)議版本,比如 TLS 1.0 版本。如果瀏覽器與服務(wù)器支持的版本不一致,服務(wù)器關(guān)閉加密通信。
一個服務(wù)器生成的隨機(jī)數(shù),稍后用于生成"對話密鑰"。注意,至此客戶端和服務(wù)端都擁有了兩個隨機(jī)數(shù)
從 Client Hello 傳過來的 Support Ciphers 里確定一份加密套件,這個套件決定了后續(xù)加密和生成摘要時具體使用哪些算法,比如 RSA 公鑰加密。
session id(sessionid 會話復(fù)用需要帶上,當(dāng)然命中 session ticket 時也需要帶上)
拓展。一般會帶上空的 renegotiation info(前提是客戶端提供了 EMPTY_SCSV 加密套件或者有renegotiation info 拓展),以表示自己支持 secure renegotiation。
除了上面這些信息,如果服務(wù)器需要確認(rèn)客戶端的身份,就會再包含一項(xiàng)請求,要求客戶端提供"客戶端證書"
服務(wù)器證書發(fā)送 (Server Certificate)發(fā)送服務(wù)器證書,將服務(wù)器配置的證書(鏈)發(fā)送到客戶端。
注意證書鏈的順序,最下層證書在前(用戶證書在前,上級證書在后)。發(fā)送的證書是二進(jìn)制格式,并非 base64 之后的格式。
服務(wù)器端秘鑰交換 (server key exchange)對于使用DHE/ECDHE非對稱密鑰協(xié)商算法的SSL握手,將發(fā)送該類型握手。
RSA 算法不會繼續(xù)該握手流程(DH、ECDH 也不會發(fā)送 server key exchange)。
ECDHE 下主要有幾點(diǎn)重要的信息:
指明自己使用的橢圓曲線(一般根據(jù)客戶端的拓展中 supported_groups 中的選擇橢圓曲線算法)。
公鑰。服務(wù)器本地計(jì)算一個大數(shù)(BIGNUM),乘上曲線的 base point,得到一個新的 point,這個 point 就是公鑰,用 04+x+y 的格式組織起來。04 表示 unconpressed point ,和客戶端的 ec_point_formats 有關(guān)。
簽名。和 RSA 握手不同,RSA 情況下,只要能值正常協(xié)商密鑰,那么必然服務(wù)器端有證書對應(yīng)的私鑰,也間接表明了服務(wù)器擁有該證書。DHE/ECDHE 不同,證書對應(yīng)的私鑰并不參與密鑰協(xié)商,如果要證明服務(wù)器擁有證書,則必然有簽名的操作(就像雙向認(rèn)證的情況下,客戶端需要發(fā)送 certificate verify)。被簽名數(shù)據(jù)從 curve type 起,至 point 的 y 為止。對于 TLS1.2,簽名前使用 client hello 拓展中提供的哈希算法。TLS1.0 和TLS1.1,如果本地證書是 ECC 證書,即若要使用 ECDSA 簽名,這種哈希算法為 SHA1,其他的情況摘要算法為md5+sha1。
計(jì)算哈希之后就調(diào)用 RSA 或者 ECDSA 進(jìn)行簽名。注意的是,TLS1.2 時要帶上 2 字節(jié)的 “Signature Hash Algorithm”。
橢圓曲線數(shù)字簽名算法(ECDSA)是使用橢圓曲線密碼(ECC)對數(shù)字簽名算法(DSA)的模擬。
DSA 算法是 RSA 算法的反向算法,服務(wù)端利用私鑰加密,客戶端用公鑰進(jìn)行驗(yàn)證,速度更快,但是不能加密,只能用于簽名驗(yàn)證,因?yàn)楣€是公開的。
DHE 下主要有幾點(diǎn)重要的信息:
指明自己使用的 DH 參數(shù),p 和 q。
服務(wù)器端計(jì)算私鑰 Xb,計(jì)算 q^Xb mod p,將結(jié)果 Pb 發(fā)給客戶端,自己僅且自己保存 Xb。
簽名流程與上述類似,不再贅述。
服務(wù)端證書請求 (certificate request)雙向認(rèn)證時,服務(wù)器會發(fā)送 certificate request,表明自己想要收到客戶端的證書。
這個類型的握手主要包含了 ca 證書的 subject ,用以告訴客戶端自己需要哪些證書,不是由這些 ca 簽發(fā)的證書“我”不要。
客戶端,例如瀏覽器在收到這個請求時,如果不存在對應(yīng)的證書,則發(fā)送一個空的 certificate 至服務(wù)器,如果存在一個證書,則發(fā)送該 certificate 至服務(wù)器。如果存在多個對應(yīng)的證書,則會彈出一個彈出框讓你選擇。
Certificate request 還包含了想要證書的簽名的類型,RSA 還是 ECDSA,對于 TLS1.2 還會包括摘要信息。
服務(wù)端結(jié)束 (Server hello done)服務(wù)器告訴客戶完成它的初始化流通消息。
客戶端證書發(fā)送 (client certificate)如果服務(wù)器端請求了客戶端的證書,客戶端即使沒有證書,也需要發(fā)送該類型的握手報(bào)文,只是這種情況下,里面的內(nèi)容為0。
如果瀏覽器有對應(yīng)的證書,則會發(fā)送證書,當(dāng)然,也有可能發(fā)送上級證書(即發(fā)送證書鏈),這個完全取決于瀏覽器。
客戶端密鑰交換 (client key exchange)ECDH/ECDHE 下比較簡單了,和 server key exchange 處理一樣,客戶端隨機(jī)生成一個大數(shù),然后乘上 base point,得到的結(jié)果就是 public key。
DHE 下客戶端計(jì)算隨機(jī)數(shù) Xa,然后該報(bào)文中的 Pubkey 就是 q^Xa mop p
RSA 下客戶端隨機(jī)生成 48 字節(jié)的預(yù)主密鑰,然后使用 pkcs1 規(guī)則填充至公鑰一樣的長度,隨后調(diào)用 RSA 進(jìn)行運(yùn)算,得到 Encrypted PreMaster。填充規(guī)則如下:00 + 02 + non_zero + 0 + pre_master。
"不管是客戶端還是服務(wù)器,都需要隨機(jī)數(shù),這樣生成的密鑰才不會每次都一樣。由于SSL協(xié)議中證書是靜態(tài)的,因此十分有必要引入一種隨機(jī)因素來保證協(xié)商出來的密鑰的隨機(jī)性。 對于RSA密鑰交換算法來說,pre-master-key本身就是一個隨機(jī)數(shù),再加上hello消息中的隨機(jī),三個隨機(jī)數(shù)通過一個密鑰導(dǎo)出器最終導(dǎo)出一個對稱密鑰。 pre master的存在在于SSL協(xié)議不信任每個主機(jī)都能產(chǎn)生完全隨機(jī)的隨機(jī)數(shù),如果隨機(jī)數(shù)不隨機(jī),那么pre master secret就有可能被猜出來,那么僅適用pre master secret作為密鑰就不合適了,因此必須引入新的隨機(jī)因素,那么客戶端和服務(wù)器加上pre master secret三個隨機(jī)數(shù)一同生成的密鑰就不容易被猜出了,一個偽隨機(jī)可能完全不隨機(jī),可是是三個偽隨機(jī)就十分接近隨機(jī)了,每增加一個自由度,隨機(jī)性增加的可不是一。"服務(wù)端證書驗(yàn)證 (Certificate verify)
發(fā)送這個類型的握手需要2個前提條件
服務(wù)器端請求了客戶端證書
客戶端發(fā)送了非0長的證書
此時,客戶端想要證明自己擁有該證書,必然需要私鑰簽名一段數(shù)據(jù)發(fā)給服務(wù)器驗(yàn)證。
簽名的數(shù)據(jù)是客戶端發(fā)送 certificate verify 前,所有收到和發(fā)送的握手信息(不包括5字節(jié)的 record)。其實(shí)這個流程和簽名 server key exchange 基本一樣。計(jì)算摘要,然后簽名運(yùn)算。
加密標(biāo)識 (Change cipher)指示 Server 從現(xiàn)在開始發(fā)送的消息都是加密過的。
服務(wù)器握手結(jié)束通知 (Encrypted handshake message)其實(shí)這個報(bào)文的目的就是告訴對端自己在整個握手過程中收到了什么數(shù)據(jù),發(fā)送了什么數(shù)據(jù)。來保證中間沒人篡改報(bào)文。
其次,這個報(bào)文作用就是確認(rèn)秘鑰的正確性。因?yàn)?Encrypted handshake message 是使用對稱秘鑰進(jìn)行加密的第一個報(bào)文,如果這個報(bào)文加解密校驗(yàn)成功,那么就說明對稱秘鑰是正確的。
計(jì)算方法也比較簡單,將之前所有的握手?jǐn)?shù)據(jù)(包括接受、發(fā)送),計(jì)算 md 哈希運(yùn)算,然后計(jì)算 prf,然后就是使用協(xié)商好的對稱密鑰進(jìn)行加密了。
MD運(yùn)算:
對于 TLS1.2,摘要算法是 sha256,即 md_result = sha256(all_handshake);
對于 TLS1.0 1.1,摘要算法是 md5 和 sha1 結(jié)果的拼接,即 md_result = md5(all_handshake) + sha1(all_handshake)。
特殊情況:如果加密套件中指定了 sha384 算法,例如 RSA_WITH_AES256_CBC_SHA384 加密套件,則無論協(xié)商使用 tls 哪個版本,都用 sha384,即 md_result = sha384(all_handshake)。
PRF運(yùn)算:
計(jì)算完哈希后,客戶端按這種格式:“client finished”+ md_result,作為 prf 的輸入。PRF 的輸出指定為 12字節(jié)。12 字節(jié)的數(shù)據(jù)前填充 4 字節(jié) message 頭部信息,就可以送入對稱加密流程進(jìn)行加密了。
PRF 運(yùn)算其實(shí)就是 P_HASH 運(yùn)算,P_HASH 就是不斷 hmac 運(yùn)算,直到計(jì)算出預(yù)定指定長度的值為止。
秘鑰交換算法HTTPS 通過 TLS 層和證書機(jī)制提供了內(nèi)容加密、身份認(rèn)證和數(shù)據(jù)完整性三大功能,可以有效防止數(shù)據(jù)被監(jiān)聽或篡改,還能抵御 MITM(中間人)攻擊。TLS 在實(shí)施加密過程中,需要用到非對稱密鑰交換和對稱內(nèi)容加密兩大算法。
對稱內(nèi)容加密強(qiáng)度非常高,加解密速度也很快,只是無法安全地生成和保管密鑰。在 TLS 協(xié)議中,應(yīng)用數(shù)據(jù)都是經(jīng)過對稱加密后傳輸?shù)?,傳輸中所使用的對稱密鑰,則是在握手階段通過非對稱密鑰交換而來。常見的 AES-GCM、ChaCha20-Poly1305,都是對稱加密算法。
非對稱密鑰交換能在不安全的數(shù)據(jù)通道中,產(chǎn)生只有通信雙方才知道的對稱加密密鑰。目前最常用的密鑰交換算法有 RSA 和 ECDHE:RSA 歷史悠久,支持度好,但不支持 PFS(Perfect Forward Secrecy);而 ECDHE 是使用了 ECC(橢圓曲線)的 DH(Diffie-Hellman)算法,計(jì)算速度快,支持 PFS。
只有非對稱密鑰交換,依然無法抵御 MITM 攻擊,還得引入身份認(rèn)證機(jī)制。對于大部分 HTTPS 網(wǎng)站來說,服務(wù)端一般通過 HTTP 應(yīng)用層的帳號體系就能完成客戶端身份認(rèn)證;而瀏覽器想要驗(yàn)證服務(wù)端身份,需要用到服務(wù)端提供的證書。
在 RSA 密鑰交換中,瀏覽器使用證書提供的 RSA 公鑰加密相關(guān)信息,如果服務(wù)端能解密,意味著服務(wù)端擁有證書對應(yīng)的私鑰,同時也能算出對稱加密所需密鑰。密鑰交換和服務(wù)端認(rèn)證合并在一起。
在 ECDHE 密鑰交換中,服務(wù)端使用證書私鑰對相關(guān)信息進(jìn)行簽名,如果瀏覽器能用證書公鑰驗(yàn)證簽名,就說明服務(wù)端確實(shí)擁有對應(yīng)私鑰,從而完成了服務(wù)端認(rèn)證。密鑰交換和服務(wù)端認(rèn)證是完全分開的。
可用于數(shù)字簽名的算法主要有 RSA 和 ECDSA,也就是目前密鑰交換 + 簽名主流選擇:
RSA 密鑰交換(無需簽名);
ECDHE 密鑰交換、RSA 簽名;
ECDHE 密鑰交換、ECDSA 簽名;
ECDH 密鑰交換、RSA 簽名;
ECDH 密鑰交換、ECDSA 簽名;
內(nèi)置 ECDSA 公鑰的證書一般被稱之為 ECC 證書,內(nèi)置 RSA 公鑰的證書就是 RSA 證書。由于 256 位 ECC Key 在安全性上等同于 3072 位 RSA Key,加上 ECC 運(yùn)算速度更快,ECDHE 密鑰交換 + ECDSA 數(shù)字簽名無疑是最好的選擇。由于同等安全條件下,ECC 算法所需的 Key 更短,所以 ECC 證書文件體積比 RSA 證書要小一些。
RSA 證書可以用于 RSA 密鑰交換(RSA 非對稱加密)或 ECDHE 密鑰交換(RSA 非對稱簽名);而 ECC 證書只能用于 ECDHE 密鑰交換(ECDSA 非對稱簽名)。
并不是所有瀏覽器都支持 ECDHE 密鑰交換,也就是說 ECC 證書的兼容性要差一些。
完全正向保密"Forward Secrecy" 或 "Perfect Forward Secrecy-完全正向保密" 協(xié)議描述了秘鑰協(xié)商(比如秘鑰交換)方法的特點(diǎn)。實(shí)際上這意味著及時你的服務(wù)器的秘鑰有危險(xiǎn),通訊僅有可能被一類人竊聽,他們必須設(shè)法獲的每次會話都會生成的秘鑰對。
完全正向保密是通過每次握手時為秘鑰協(xié)商隨機(jī)生成密鑰對來完成(和所有會話一個 key 相反)。實(shí)現(xiàn)這個技術(shù)(提供完全正向保密-Perfect Forward Secrecy)的方法被稱為 "ephemeral"。
通常目前有2個方法用于完成完全正向保密(Perfect Forward Secrecy):
DHE - 一個迪菲-赫爾曼密鑰交換密鑰協(xié)議(Diffie Hellman key-agreement protocol)短暫(ephemeral)版本。
ECDHE - 一個橢圓曲線密鑰交換密鑰協(xié)議( Elliptic Curve Diffie Hellman key-agreement protocol)短暫(ephemeral)版本。
短暫(ephemeral)方法有性能缺點(diǎn),因?yàn)樯?key 非常耗費(fèi)資源。
以下內(nèi)容參考文獻(xiàn):TLS/SSL 協(xié)議詳解 (30) SSL中的RSA、DHE、ECDHE、ECDH流程與區(qū)別
RSA 密鑰交換算法我們先來看看傳統(tǒng)的秘鑰交換算法—— RSA 秘鑰交換算法。它是不符合完全正向保密的,但是是我們上面講的經(jīng)典秘鑰交換。
RSA的核心涉及公鑰私鑰的概念
使用公鑰加密的數(shù)據(jù)只有私鑰能解密
使用私鑰加密的數(shù)據(jù)只有公鑰能解密
我們構(gòu)建這么一種場景,服務(wù)器配置有公鑰+私鑰,客戶端是離散的。
RSA算法流程文字描述如下:
任意客戶端對服務(wù)器發(fā)起帶有隨機(jī)碼的請求,服務(wù)器發(fā)回另一個隨機(jī)碼和自己的公鑰到客戶端(公鑰明文傳輸)。
客戶端生成隨機(jī)碼,和前兩個隨機(jī)碼合并,使用隨機(jī)數(shù)算法生成一個密鑰 S,使用收到的公鑰進(jìn)行加密,生成 C,把 C 發(fā)送到服務(wù)器。
服務(wù)器收到 C,使用公鑰對應(yīng)的私鑰進(jìn)行解密,得到 S。
上述交換步驟后,客戶端和服務(wù)器都得到了 S,S 為密鑰(預(yù)主密鑰)。
我們來看看上述過程中,為何第三方無法得到 S。首先第一步后,客戶端有公鑰,服務(wù)器有公鑰和私鑰。由于公鑰是明文傳輸?shù)?,所以可以假設(shè)第三方也有公鑰。
第二步后,客戶端發(fā)送 C,服務(wù)器能夠使用自己的私鑰進(jìn)行解密,而第三方只有公鑰,無法解密。即第三方無法計(jì)算得到 S。
上述中,服務(wù)器發(fā)送的公鑰在 SSL 中是通過 certificate 報(bào)文發(fā)送的,certificate 中的包含了公鑰。C 是通過 Client key exchange 報(bào)文發(fā)送的。
其實(shí),在實(shí)際 SSL 實(shí)際設(shè)計(jì)中,S 其實(shí)并沒有直接被當(dāng)成密鑰加密,這里為了描述原理,省去了對 S 后續(xù)進(jìn)行 KDF 哈希等操作,并不影響實(shí)際理解 RSA。
RSA 有一個問題,就是如果私鑰泄漏,即私鑰被第三方知道,那么第三方就能從 C 中解密得到 S,即只要保存所有的 A 和 B 的報(bào)文,等到私鑰被泄漏的那一天,或者有辦法快從 C 中計(jì)算 S 的方法出現(xiàn)(量子計(jì)算機(jī)分解大素?cái)?shù)),那么 A 和 B 就沒有什么私密性可言了。
這就是所謂的前向不安全,私鑰參與了密鑰交換,安全性取決于私鑰是否安全保存。
DHE 密鑰交換算法DHE算法流程文字描述如下:
客戶端計(jì)算一個隨機(jī)值 Xa,使用 Xa 作為指數(shù),即計(jì)算 Pa = q^Xa mod p,其中 q 和 p 是全世界公認(rèn)的一對值??蛻舳税?Pa 發(fā)送至服務(wù)器,Xa 作為自己私鑰,僅且自己知道。
服務(wù)器和客戶端計(jì)算流程一樣,生成一個隨機(jī)值 Xb,使用 Xb 作為指數(shù),計(jì)算 Pb = q^Xb mod p,將結(jié)果 Pb發(fā)送至客戶端,Xb 僅自己保存。
客戶端收到 Pb 后計(jì)算 Sa = Pb ^Xa mod p;服務(wù)器收到 Pa 后計(jì)算 Sb = Pa^Xb mod p
算法保證了 Sa = Sb = S,故密鑰交換成功,S 為密鑰(預(yù)主密鑰)。
上述途中,Sa 和 Sb 得到的結(jié)果是相同的,即記為 S。
上述密鑰交換流程中,和 RSA 密鑰交換有較大不同,DHE 密鑰交換時,服務(wù)器私鑰沒有參與進(jìn)來。也就是說,私鑰即使泄漏,也不會導(dǎo)致會話加密密鑰 S 被第三方解密。
實(shí)際使用過程中,私鑰的功能被削弱到用來身份認(rèn)證。
DHE 參數(shù)和 Pb 都是通過 server key exchange 發(fā)送給客戶端,Pa 通過 client key exchange 發(fā)送給服務(wù)器。server key exchange 的結(jié)尾處需要使用服務(wù)器私鑰對該報(bào)文本身進(jìn)行簽名,以表明自己擁有私鑰。
ECDHE 密鑰交換算法只要理解 DHE 密鑰交換原理,那么理解 ECDHE 密鑰交換原理其實(shí)并不難(如果不想深究的話)。
ECDHE 的運(yùn)算是把 DHE 中模冪運(yùn)算替換成了點(diǎn)乘運(yùn)算,速度更快,可逆更難。
ECDHE 算法流程文字描述如下:
客戶端隨機(jī)生成隨機(jī)值 Ra,計(jì)算 Pa(x, y) = Ra * Q(x, y),Q(x, y) 為全世界公認(rèn)的某個橢圓曲線算法的基點(diǎn)。將 Pa(x, y) 發(fā)送至服務(wù)器。
服務(wù)器隨機(jī)生成隨機(jī)值 Pb,計(jì)算 Pb(x,y) = Rb * Q(x, y)。將 Pb(x, y) 發(fā)送至客戶端。
客戶端計(jì)算 Sa(x, y) = Ra * Pb(x, y);服務(wù)器計(jì)算 Sb(x, y) = Rb *Pa(x, y)
算法保證了 Sa = Sb = S,提取其中的 S 的 x 向量作為密鑰(預(yù)主密鑰)。
SSL 協(xié)議中,上圖中橢圓曲線名和 Pb 通過 server key exchange 報(bào)文發(fā)送;Pa 通過 client key exchange 報(bào)文發(fā)送。
ECDHE 與 ECDH 算法的區(qū)別字面少了一個 E,E 代表了“臨時”,即在握手流程中,作為服務(wù)器端,ECDH 少了一步計(jì)算 Pb 的過程,Pb 用證書中的公鑰代替,而證書對應(yīng)的私鑰就是 Xb。由此可見,使用 ECDH 密鑰交換算法,服務(wù)器必須采用 ECC 證書;服務(wù)器不發(fā)送 server key exchange 報(bào)文,因?yàn)榘l(fā)送 certificate 報(bào)文時,證書本身就包含了 Pb 信息。
ECDHE 與 RSA 的區(qū)別ECDHE(DHE) 算法屬于 DH 類密鑰交換算法, 私鑰不參與密鑰的協(xié)商,故即使私鑰泄漏,客戶端和服務(wù)器之間加密的報(bào)文都無法被解密。由于 ECDHE 每條會話都重新計(jì)算一個密鑰(Ra、Rb),故一條會話被解密后,其他會話仍舊安全。
然而,ECDH 算法服務(wù)器端的私鑰是固定的,即證書的私鑰作為 Rb,故 ECDH 不被認(rèn)為前向安全,因?yàn)樗借€泄漏相當(dāng)于 Rb 泄漏,Rb泄漏,導(dǎo)致會話密鑰可被第三方計(jì)算。
加密套件以下內(nèi)容來源:SSL協(xié)議中的加密套件
加密套件(CipherList)是指在 ssl 通信中,服務(wù)器和客戶端所使用的加密算法的組合。在 ssl 握手初期,客戶端將自身支持的加密套件列表發(fā)送給服務(wù)器;在握手階段,服務(wù)器根據(jù)自己的配置從中盡可能的選出一個套件,作為之后所要使用的加密方式。這些算法包括:認(rèn)證算法、密鑰交換算法、對稱算法和摘要算法等。
每種加密套件的名字里包含了四部分信息,分別是:
第一部分是密鑰交換,用于決定客戶端與服務(wù)器之間在握手的過程中如何認(rèn)證。使用非對稱加密算法來生成會話密鑰,因?yàn)榉菍ΨQ算法不會將重要數(shù)據(jù)在通信中傳輸。用到的算法包括 RSA,Diffie-Hellman,ECDH,PSK 等
第二部分是加密算法,主要是對傳輸?shù)臄?shù)據(jù)進(jìn)行加密傳輸用的。一般有對稱加和非對稱加密,但是非對稱加密算法太耗性能,再者有些非對稱加密算法有內(nèi)容長度的限制,所以真正要傳輸?shù)臄?shù)據(jù)會使用對稱加密來進(jìn)行加密。算法名稱后通常會帶有兩個數(shù)字,分別表示密鑰的長度和初始向量的長度,比如 DES 56/56, RC2 56/128, RC4 128/128, AES 128/128, AES 256/256
第三部分是會話校驗(yàn)(MAC)算法,為了防止握手本身被竄改(這里極容易和證書簽名算法混淆)。算法包括MD5,SHA等。
第四部分是 PRF(偽隨機(jī)數(shù)函數(shù)),用于生成“master secret”。
例如 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
從其名字可知,它是:
基于 TLS 協(xié)議的;
使用 ECDHE、RSA 作為密鑰交換算法與證書簽名類型;
加密算法是 AES(密鑰和初始向量的長度都是 256);
MAC 算法(這里就是哈希算法)是 SHA。
在客戶端和服務(wù)器端建立安全連接之前,雙方都必須指定適合自己的加密套件。加密套件的選擇可以通過組合的字符串來控制。
服務(wù)器在選擇算法時,會有優(yōu)先級,是以客戶端提供的的為最優(yōu),還是服務(wù)器端配置的為最優(yōu)。所謂的客戶端最優(yōu),就是根據(jù)客戶端提供的加密套件,從上到下,看是否有本地支持的,有的話則使用。所謂服務(wù)器端最優(yōu),就是服務(wù)器端根據(jù)自身配置的加密套件順序,一個個在 client hello 中找,找到了就使用。
其次,當(dāng)服務(wù)器配置 ECC 證書時,加密套件只能選擇 XXX_ECDSA_XXX 或者 ECDH_XXX。當(dāng)服務(wù)器配置 RSA 證書時,只能選擇 RSA_XXX 或者 ECDHE_RSA_XXX 形式的加密套件。
需要注意的是,如果加密套件選擇 ECDH_RSA 或者 ECDH_ECDSA 時,由于 ECDH 加密套件默認(rèn)表明了握手需要 ECC 公鑰(即 ECC 證書的公鑰充當(dāng)握手中 server key exchange 中的公鑰,證書的私鑰同樣也是握手過程中的私鑰,握手過程不需要 server key exchange),所以第二部分 _RSA 和 _ECDSA 表明的是想要的服務(wù)器證書簽名類型。
換句話說,CA 頒發(fā)的證書可以是用 CA 自己的 RSA 私鑰進(jìn)行簽名的 RSA 證書,也可以用 CA 的 ECC 私鑰進(jìn)行簽名的 ECC 證書。具體是哪個,取決于 CA 部門和申請證書的類別。
證書內(nèi)部存儲的 CSR 的公鑰是具體申請證書人員生成的,可以是 RSA 算法的公鑰,也可以是 ECC 算法的公鑰。取決于提交給 CA 之前生成的 CSR 方法。
比如說服務(wù)器選擇了 ECDH_RSA 加密套件,但是發(fā)送的證書卻是 ECDSA 簽名的證書,雖然說證書簽名類型不影響整個握手,但是對于校驗(yàn)嚴(yán)格的客戶端,這種情況可能會導(dǎo)致客戶端斷開鏈接。
加密套件也可以用字符串的形式,舉例:ALL:!ADH:RC4+RSA:+SSLv2:@STRENGTH
Openssl 定義了 4 中選擇符號:“+”,“-”,“!”,“@”。其中,“+”表示取交集;“-”表示臨時刪除一個算法;“!”表示永久刪除一個算法;“@“表示了排序方法。
多個描述之間可以用“:”、“,”、“ ”、“;”來分開。選擇加密套件的時候按照從左到的順序構(gòu)成雙向鏈表,存放與內(nèi)存中。
ALL:!ADH:RC4+RSA:+SSLv2:@STRENGTH 表示的意義是:
首先選擇所有的加密套件(不包含eNULL,即空對稱加密算法),然后在得到的雙向鏈表之中去掉身份驗(yàn)證采用 DH 的加密套件;加入包含 RC4 算法并將包含 RSA 的加密套件放在雙向鏈表的尾部;再將支持 SSLV2 的加密套件放在尾部;最后得到的結(jié)果按照安全強(qiáng)度進(jìn)行排序。
可以使用命令 : openssl ciphers -V "ALL:!ADH:RC4+RSA:+SSLv2:@STRENGTH" | column -t 來查看具體加密套件。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/30897.html
摘要:當(dāng)此時的套接字不可寫的時候,會自動放入緩沖區(qū)中。當(dāng)大于高水線時,會自動調(diào)用回調(diào)函數(shù)。寫就緒狀態(tài)當(dāng)監(jiān)控到套接字進(jìn)入了寫就緒狀態(tài)時,就會調(diào)用函數(shù)。如果為,說明此時異步客戶端雖然建立了連接,但是還沒有調(diào)用回調(diào)函數(shù),因此這時要調(diào)用函數(shù)。 前言 上一章我們說了客戶端的連接 connect,對于同步客戶端來說,連接已經(jīng)建立成功;但是對于異步客戶端來說,此時可能還在進(jìn)行 DNS 的解析,on...
摘要:對于服務(wù)端來說,緩存默認(rèn)是不能使用的,可以通過調(diào)用函數(shù)來進(jìn)行設(shè)置生效。在回調(diào)函數(shù)中,首先申請一個大數(shù)數(shù)據(jù)結(jié)構(gòu),然后將其設(shè)定為,該值表示公鑰指數(shù),然后利用函數(shù)生成秘鑰。此時需要調(diào)用函數(shù)將新的連接與綁定。 前言 上一篇文章我們講了 OpenSSL 的原理,接下來,我們來說說如何利用 openssl 第三方庫進(jìn)行開發(fā),來為 tcp 層進(jìn)行 SSL 隧道加密 OpenSSL 初始化 在 sw...
摘要:兩個函數(shù)是可選回調(diào)函數(shù)。附帶了一組可信任證書。應(yīng)該注意的是,驗(yàn)證失敗并不意味著連接不能使用。在對證書進(jìn)行驗(yàn)證時,有一些安全性檢查并沒有執(zhí)行,包括證書的失效檢查和對證書中通用名的有效性驗(yàn)證。 前言 swoole_client 提供了 tcp/udp socket 的客戶端的封裝代碼,使用時僅需 new swoole_client 即可。 swoole 的 socket client 對比...
摘要:如果在調(diào)用之前我們設(shè)置了,但是不在第二個進(jìn)程啟動前這個套接字,那么第二個進(jìn)程仍然會在調(diào)用函數(shù)的時候出錯。 前言 本節(jié)主要介紹 server 模塊進(jìn)行初始化的代碼,關(guān)于初始化過程中,各個屬性的意義,可以參考官方文檔: SERVER 配置選項(xiàng) 關(guān)于初始化過程中,用于監(jiān)聽的 socket 綁定問題,可以參考: UNP 學(xué)習(xí)筆記——基本 TCP 套接字編程 UNP 學(xué)習(xí)筆記——套接字選項(xiàng) 構(gòu)造...
摘要:判斷客戶端是否配置了檢測或者長度檢測,如果配置了就調(diào)用接受完整的數(shù)據(jù)包,這兩天會調(diào)用,進(jìn)而調(diào)用函數(shù)。異步客戶端接受數(shù)據(jù)異步的客戶端接受數(shù)據(jù)調(diào)用的和同步的客戶端相同,都是調(diào)用函數(shù)。 recv 接受數(shù)據(jù) 客戶端接受數(shù)據(jù)需要指定緩存區(qū)最大長度,就是下面的 buf_len,flags 用于指定是否設(shè)置 waitall 標(biāo)志,如果設(shè)定了 waitall 就必須設(shè)定準(zhǔn)確的 size,否則會一直等...
閱讀 718·2021-11-16 11:44
閱讀 3551·2019-08-26 12:13
閱讀 3246·2019-08-26 10:46
閱讀 2361·2019-08-23 12:37
閱讀 1192·2019-08-22 18:30
閱讀 2536·2019-08-22 17:30
閱讀 1843·2019-08-22 17:26
閱讀 2295·2019-08-22 16:20