SSL/TLS
簡介
SSL/TLS secure sockets layer/transport layer security
SSL協(xié)議位于TCP/IP協(xié)議與各種應(yīng)用層協(xié)議之間,為數(shù)據(jù)通訊提供安全支持。SSL協(xié)議可分為兩層:
SSL記錄協(xié)議(SSL Record Protocol):它建立在可靠的傳輸協(xié)議(如TCP)之上偷线,為高層協(xié)議提供數(shù)據(jù)封裝历帚、壓縮、加密等基本功能的支持屯换。
SSL握手協(xié)議(SSL Handshake Protocol):它建立在SSL記錄協(xié)議之上编丘,用于在實際的數(shù)據(jù)傳輸開始前,通訊雙方進(jìn)行身份認(rèn)證彤悔、協(xié)商加密算法瘪吏、交換加密密鑰等.
SSL協(xié)議提供的服務(wù)主要有:
- 認(rèn)證用戶和服務(wù)器,確保數(shù)據(jù)發(fā)送到正確的客戶機(jī)和服務(wù)器蜗巧;
- 加密數(shù)據(jù)以防止數(shù)據(jù)中途被竊日泼摺;
- 維護(hù)數(shù)據(jù)的完整性幕屹,確保數(shù)據(jù)在傳輸過程中不被改變蓝丙。
由于非對稱加密的速度比較慢,所以它一般用于密鑰交換望拖,雙方通過公鑰算法協(xié)商出一份密鑰渺尘,然后通過對稱加密來通信,當(dāng)然说敏,為了保證數(shù)據(jù)的完整性鸥跟,在加密前要先經(jīng)過HMAC的處理
SSL/TLS協(xié)議的基本思路是采用公鑰加密法,也就是說盔沫,客戶端先向服務(wù)器端索要公鑰医咨,然后用公鑰加密信息,服務(wù)器收到密文后架诞,用自己的私鑰解密拟淮。
(1)如何保證公鑰不被篡改?
解決方法:將公鑰放在數(shù)字證書中谴忧。只要證書是可信的很泊,公鑰就是可信的角虫。
(2)公鑰加密計算量太大,如何減少耗用的時間委造?
解決方法:每一次對話(session)书聚,客戶端和服務(wù)器端都生成一個"對話密鑰"(session key)蚁鳖,用它來加密信息颓影。由于"對話密鑰"是對稱加密音五,所以運算速度非常快亮垫,而服務(wù)器公鑰只用于加密"對話密鑰"本身模软,這樣就減少了加密運算的消耗時間。
故SSL/TLS協(xié)議基本過程:
- 客戶端向服務(wù)器端索要并驗證公鑰饮潦。
- 雙方協(xié)商生成"對話密鑰"燃异。
- 雙方采用"對話密鑰"進(jìn)行加密通信。
1继蜡,2階段即握手階段回俐,明文傳輸。
- client_hello
客戶端發(fā)起請求稀并,以明文傳輸請求信息仅颇,包含版本信息,加密套件候選列表碘举,壓縮算法候選列表忘瓦,隨機(jī)數(shù),擴(kuò)展字段等信息引颈,相關(guān)信息如下:支持的最高TSL協(xié)議版本version耕皮,從低到高依次 SSLv2 SSLv3 TLSv1 TLSv1.1 TLSv1.2,當(dāng)前基本不再使用低于 TLSv1 的版本;
客戶端支持的加密套件 cipher suites 列表蝙场, 每個加密套件對應(yīng)前面 TLS 原理中的四個功能的組合:認(rèn)證算法 Au (身份驗證)凌停、密鑰交換算法 KeyExchange(密鑰協(xié)商)、對稱加密算法 Enc (信息加密)和信息摘要 Mac(完整性校驗);
支持的壓縮算法 compression methods 列表售滤,用于后續(xù)的信息壓縮傳輸;
隨機(jī)數(shù) random_C罚拟,用于后續(xù)的密鑰的生成;
擴(kuò)展字段 extensions,支持協(xié)議與算法的相關(guān)參數(shù)以及其它輔助信息等完箩,常見的 SNI 就屬于擴(kuò)展字段
- server_hello+server_certificate+sever_hello_done
server_hello, 服務(wù)端返回協(xié)商的信息結(jié)果赐俗,包括選擇使用的協(xié)議版本 version,選擇的加密套件 cipher suite嗜憔,選擇的壓縮算法 compression method秃励、隨機(jī)數(shù) random_S 等,其中隨機(jī)數(shù)用于后續(xù)的密鑰協(xié)商;
server_certificates, 服務(wù)器端配置對應(yīng)的證書鏈吉捶,用于身份驗證與密鑰交換;
server_hello_done夺鲜,通知客戶端 server_hello 信息發(fā)送結(jié)束; - 證書校驗
[證書鏈]的可信性 trusted certificate path,方法如前文所述;
證書是否吊銷 revocation呐舔,有兩類方式離線 CRL 與在線 OCSP币励,不同的客戶端行為會不同;
有效期 expiry date,證書是否在有效時間范圍;
域名 domain珊拼,核查證書域名是否與當(dāng)前的訪問域名匹配食呻,匹配規(guī)則后續(xù)分析; - client_key_exchange+change_cipher_spec+encrypted_handshake_message
client_key_exchange,合法性驗證通過之后澎现,客戶端計算產(chǎn)生隨機(jī)數(shù)字 Pre-master仅胞,并用證書公鑰加密,發(fā)送給服務(wù)器;
此時客戶端已經(jīng)獲取全部的計算協(xié)商密鑰需要的信息:兩個明文隨機(jī)數(shù) random_C 和 random_S 與自己計算產(chǎn)生的 Pre-master剑辫,計算得到協(xié)商密鑰;
enc_key=Fuc(random_C, random_S, Pre-Master)
change_cipher_spec干旧,客戶端通知服務(wù)器后續(xù)的通信都采用協(xié)商的通信密鑰和加密算法進(jìn)行加密通信;
encrypted_handshake_message,結(jié)合之前所有通信參數(shù)的 hash 值與其它相關(guān)信息生成一段數(shù)據(jù)妹蔽,采用協(xié)商密鑰 session secret 與算法進(jìn)行加密椎眯,然后發(fā)送給服務(wù)器用于數(shù)據(jù)與握手驗證; - change_cipher_spec+encrypted_handshake_message
服務(wù)器用私鑰解密加密的 Pre-master 數(shù)據(jù),基于之前交換的兩個明文隨機(jī)數(shù) random_C 和 random_S胳岂,計算得到協(xié)商密鑰:enc_key=Fuc(random_C, random_S, Pre-Master);
計算之前所有接收信息的 hash 值编整,然后解密客戶端發(fā)送的 encrypted_handshake_message,驗證數(shù)據(jù)和密鑰正確性;
change_cipher_spec, 驗證通過之后乳丰,服務(wù)器同樣發(fā)送 change_cipher_spec 以告知客戶端后續(xù)的通信都采用協(xié)商的密鑰與算法進(jìn)行加密通信;
encrypted_handshake_message, 服務(wù)器也結(jié)合所有當(dāng)前的通信參數(shù)信息生成一段數(shù)據(jù)并采用協(xié)商密鑰 session secret 與算法加密并發(fā)送到客戶端; - 握手結(jié)束
客戶端計算所有接收信息的 hash 值掌测,并采用協(xié)商密鑰解密 encrypted_handshake_message,驗證服務(wù)器發(fā)送的數(shù)據(jù)和密鑰产园,驗證通過則握手完成; - 加密通信
開始使用協(xié)商密鑰與算法進(jìn)行加密通信汞斧。
CA
CA: 證書授權(quán)中心( certificate authority)
- CA本身是受信任的
- 給他受信任的申請對象頒發(fā)證書
CA 的證書 ca.crt 和 SSL Server的證書 server.crt 是什么關(guān)系呢?
- SSL Server 自己生成一個 私鑰/公鑰對淆两。server.key/server.pub
- server.pub 生成一個請求文件 server.req. 請求文件中包含有 server 的一些信息断箫,如域名/申請者/公鑰等。
- server 將請求文件 server.req 遞交給 CA秋冰,CA驗明正身后仲义,將用 ca.key和請求文件加密生成 server.crt
- 由于 ca.key 和 ca.crt 是一對, 于是 ca.crt 可以解密 server.crt.
在實際應(yīng)用中:如果 SSL Client 想要校驗 SSL server.那么 SSL server 必須要將他的證書 server.crt 傳給 client.然后 client 用 ca.crt 去校驗 server.crt 的合法性。如果是一個釣魚網(wǎng)站剑勾,那么CA是不會給他頒發(fā)合法server.crt證書的埃撵,這樣client 用ca.crt去校驗,就會失敗虽另。比如瀏覽器作為一個 client,你想訪問合法的淘寶網(wǎng)站https://www.taobao.com, 結(jié)果不慎訪問到 https://wwww.jiataobao.com ,那么瀏覽器將會檢驗到這個假淘寶釣魚網(wǎng)站的非法性暂刘,提醒用戶不要繼續(xù)訪問!這樣就可以保證了client的所有https訪問都是安全的捂刺。
單向認(rèn)證指的是只有一個對象校驗對端的證書合法性谣拣。
通常都是client來校驗服務(wù)器的合法性募寨。那么client需要一個ca.crt,服務(wù)器需要server.crt,server.key
雙向認(rèn)證指的是相互校驗,服務(wù)器需要校驗每個client,client也需要校驗服務(wù)器森缠。
server 需要 server.key 拔鹰、server.crt 、ca.crt
client 需要 client.key 贵涵、client.crt 列肢、ca.crt
證書
digital certificate , public key certificate
證書標(biāo)準(zhǔn)
X.509 - 這是一種證書標(biāo)準(zhǔn),主要定義了證書中應(yīng)該包含哪些內(nèi)容.其詳情可以參考RFC5280,SSL使用的就是這種證書標(biāo)準(zhǔn).
編碼格式
同樣的X.509證書,可能有不同的編碼格式,目前有以下兩種編碼格式.
PEM - Privacy Enhanced Mail,打開看文本格式,以"-----BEGIN..."開頭, "-----END..."結(jié)尾,內(nèi)容是BASE64編碼.
查看PEM格式證書的信息:openssl x509 -in certificate.pem -text -noout
Apache和*NIX服務(wù)器偏向于使用這種編碼格式.
DER - Distinguished Encoding Rules,打開看是二進(jìn)制格式,不可讀.
查看DER格式證書的信息:openssl x509 -in certificate.der -inform der -text -noout
Java和Windows服務(wù)器偏向于使用這種編碼格式.
相關(guān)后綴
雖然我們已經(jīng)知道有PEM和DER這兩種編碼格式,但文件擴(kuò)展名并不一定就叫"PEM"或者"DER",常見的擴(kuò)展名除了PEM和DER還有以下這些,它們除了編碼格式可能不同之外,內(nèi)容也有差別,但大多數(shù)都能相互轉(zhuǎn)換編碼格式.
CRT - CRT應(yīng)該是certificate的三個字母,其實還是證書的意思,常見于*NIX系統(tǒng),有可能是PEM編碼,也有可能是DER編碼,大多數(shù)應(yīng)該是PEM編碼,相信你已經(jīng)知道怎么辨別.
CER - 還是certificate,還是證書,常見于Windows系統(tǒng),同樣的,可能是PEM編碼,也可能是DER編碼,大多數(shù)應(yīng)該是DER編碼.
KEY - 通常用來存放一個公鑰或者私鑰,并非X.509證書,編碼同樣的,可能是PEM,也可能是DER.
查看KEY的辦法:openssl rsa -in mykey.key -text -noout
如果是DER格式的話,同理應(yīng)該這樣了:openssl rsa -in mykey.key -text -noout -inform der
CSR - Certificate Signing Request,即證書簽名請求,這個并不是證書,而是向權(quán)威證書頒發(fā)機(jī)構(gòu)獲得簽名證書的申請,其核心內(nèi)容是一個公鑰(當(dāng)然還附帶了一些別的信息),在生成這個申請的時候,同時也會生成一個私鑰,私鑰要自己保管好.
查看的辦法:openssl req -noout -text -in my.csr (如果是DER格式的話照舊加上-inform der,這里不寫了)
PFX/P12 - 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 -in certificate.crt -inkey privateKey.key -out certificate.pfx -certfile CACert.crt
其中CACert.crt是CA(權(quán)威證書頒發(fā)機(jī)構(gòu))的根證書,有的話也通過-certfile參數(shù)一起帶進(jìn)去.這么看來,PFX其實是個證書密鑰庫.
JKS - 即Java Key Storage,這是Java的專利,跟OpenSSL關(guān)系不大,利用Java的一個叫"keytool"的工具,可以將PFX轉(zhuǎn)為JKS,當(dāng)然了,keytool也能直接生成JKS,不過在此就不多表了.
證書編碼轉(zhuǎn)換
PEM轉(zhuǎn)為DER openssl x509 -in cert.crt -outform der -out cert.der
DER轉(zhuǎn)為PEM openssl x509 -in cert.crt -inform der -outform pem -out cert.pem
(提示:要轉(zhuǎn)換KEY文件也類似,只不過把x509換成rsa,要轉(zhuǎn)CSR的話,把x509換成req...)
獲取證書
向權(quán)威證書頒發(fā)機(jī)構(gòu)申請證書
用這命令生成一個csr: openssl req -newkey rsa:2048 -new -nodes -keyout my.key -out my.csr
把csr交給權(quán)威證書頒發(fā)機(jī)構(gòu),權(quán)威證書頒發(fā)機(jī)構(gòu)對此進(jìn)行簽名,完成.保留好csr,當(dāng)權(quán)威證書頒發(fā)機(jī)構(gòu)頒發(fā)的證書過期的時候,你還可以用同樣的csr來申請新的證書,key保持不變.
生成自簽名的證書
openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout key.pem -out cert.pem
在生成證書的過程中會要你填一堆的東西,其實真正要填的只有Common Name,通常填寫你服務(wù)器的域名,如"yourcompany.com",或者你服務(wù)器的IP地址,其它都可以留空的.
證書工作流
1)申請認(rèn)證:服務(wù)器需自己生成公鑰私鑰對pub_svr & pri_svr瓷马,同時根據(jù) pub_svr 生成請求文件 csr,提交給CA,csr中含有公鑰跨晴、組織信息欧聘、個人信息(域名)等信息。(server.req就是csr請求文件)
2)審核信息:CA通過線上坟奥、線下等多種手段驗證申請者提供信息的真實性树瞭,如組織是否存在、企業(yè)是否合法爱谁,是否擁有域名的所有權(quán)等晒喷。
3)簽發(fā)證書:如信息審核通過,CA會向申請者簽發(fā)認(rèn)證文件-證書访敌。
證書包含以下信息:申請者公鑰凉敲、申請者的組織信息和個人信息、簽發(fā)機(jī)構(gòu) CA的信息寺旺、有效時間爷抓、證書序列號等信息的明文,同時包含一個簽名阻塑。
簽名的產(chǎn)生算法:首先蓝撇,使用散列函數(shù)計算公開的明文信息的信息摘要,然后陈莽,采用 CA的私鑰對信息摘要進(jìn)行加密渤昌,密文即簽名。(生成server.crt)
4)返回證書:client如果請求驗證服務(wù)器走搁,服務(wù)器需返回證書文件独柑。(圖一中handshake傳回server.crt)
5)client驗證證書:client讀取證書中的相關(guān)的明文信息,采用相同的散列函數(shù)計算得到信息摘要私植,然后忌栅,利用對應(yīng) CA的公鑰解密簽名數(shù)據(jù),對比證書的信息摘要曲稼,如果一致索绪,則可以確認(rèn)證書的合法性湖员,即公鑰合法≌叽海客戶端然后驗證證書相關(guān)的域名信息破衔、有效時間是否吊銷等信息清女。
客戶端會內(nèi)置信任CA的證書信息(包含公鑰)钱烟,如果CA不被信任,則找不到對應(yīng) CA的證書嫡丙,證書也會被判定非法拴袭。(圖一中check可選,我們可以選擇不驗證服務(wù)器證書的有效性)
6)秘鑰協(xié)商:驗證通過后曙博,Server和Client將進(jìn)行秘鑰協(xié)商拥刻。接下來Server和Client會采用對稱秘鑰加密。(對稱加密時間性能優(yōu))(圖一中 pre-master/change_cipher_spec/encrypted_handshake_message過程)
7)數(shù)據(jù)傳輸:Server和Client采用對稱秘鑰加密解密數(shù)據(jù)父泳。
實踐
openssl x509 -noout -text -in baiducom.crt
查看證書
生成證書
#
# Generate the certificates and keys for testing.
#
PROJECT_NAME="TLS Project"
# Generate the openssl configuration files.
cat > ca_cert.conf << EOF
[ req ]
distinguished_name = req_distinguished_name
prompt = no
[ req_distinguished_name ]
O = $PROJECT_NAME Dodgy Certificate Authority
EOF
cat > server_cert.conf << EOF
[ req ]
distinguished_name = req_distinguished_name
prompt = no
[ req_distinguished_name ]
O = $PROJECT_NAME
CN = 192.168.111.100
EOF
cat > client_cert.conf << EOF
[ req ]
distinguished_name = req_distinguished_name
prompt = no
[ req_distinguished_name ]
O = $PROJECT_NAME Device Certificate
CN = 192.168.111.101
EOF
mkdir ca
mkdir server
mkdir client
mkdir certDER
# private key generation
openssl genrsa -out ca.key 1024
openssl genrsa -out server.key 1024
openssl genrsa -out client.key 1024
# cert requests
openssl req -out ca.req -key ca.key -new \
-config ./ca_cert.conf
openssl req -out server.req -key server.key -new \
-config ./server_cert.conf
openssl req -out client.req -key client.key -new \
-config ./client_cert.conf
# generate the actual certs.
openssl x509 -req -in ca.req -out ca.crt \
-sha1 -days 5000 -signkey ca.key
openssl x509 -req -in server.req -out server.crt \
-sha1 -CAcreateserial -days 5000 \
-CA ca.crt -CAkey ca.key
openssl x509 -req -in client.req -out client.crt \
-sha1 -CAcreateserial -days 5000 \
-CA ca.crt -CAkey ca.key
openssl x509 -in ca.crt -outform DER -out ca.der
openssl x509 -in server.crt -outform DER -out server.der
openssl x509 -in client.crt -outform DER -out client.der
mv ca.crt ca.key ca/
mv server.crt server.key server/
mv client.crt client.key client/
mv ca.der server.der client.der certDER/
rm *.conf
rm *.req
rm *.srl
驗證
openssl verify -CAfile ca/ca.crt server/server.crt
openssl verify -CAfile ca/ca.crt client/client.crt