一、構建HTTPS網站
1. 獲取證書和密鑰對
1.1.1 自簽名證書
當瀏覽器發現證書是自簽名的,會提示用戶是否信任該證書。一般企業內部應用可以選擇自簽名證書。
第1步 生成私鑰對和CSR
CSR用來請求證書,其中包含了服務器的密鑰對,CA機構收到請求后會驗證CSR請求的簽名。
openssl req -newkey rsa:1024 -nodes -keyout my_key.pem -out mykey_csr.pem
提示輸入中最重要的是輸入域名信息:Common Name。
第2步 生成自簽名證書
就是模擬CA機構對盲目簽名:
openssl x509 -signkey my_key.pem -in mykey_csr.pem -req -days 365 -out my_cert.pem
生成my_cert.pem即簽名后的證書:
1.1.2 向CA機構申請證書
- 向專門的CA機構申請;
- 向代理機構申請,如一些云廠商。
證書申請的方式:
- 向CA發送CSR;
- CA統一生成證書和密鑰對,但泄露了自己的私鑰。
申請時,CA機構通過DNS TXT記錄或服務器上一個特殊的txt文件來校驗域名所有者。
1.1.3 使用Let’s Encrypt證書
Let’s Encrypt可以申請免費的證書,作為一個CA機構得到了很多大公司的支持,它定義了ACME協議,將管理證書的流程進行了標準化。
可以使用基于ACME協議的客戶端在Let’s Encrypt管理證書,官方推薦Certbot客戶端。
# 下載Certbot客戶端
git clone https://github.com/certbot/certbot
cd certbot
# 生成證書,-w表示代碼根目錄,-d要申請證書的域名,--webroot表示安裝插件。
./certbot-auto certonly --webroot -w /usr/Nginx/web -d www.mydomain.com
運行結束在/etc/letsencrypt/live/www.mydomain.com下生成4個文件,最重要的是:
- fullchain.pem 完整證書鏈
- privkey.pem 私鑰
另外還有: - cert.pem
- chain.pem
webroot 插件用來校驗申請者身份,該命令需要在mydomain主機上運行,主機web在/usr/nginx/web下。
2. 部署證書和密鑰對
1.2.1 Nginx 下部署
http{
#http節點中可以添加多個server節點
server{
#監聽443端口
listen 443;
#對應的域名,把mydomain.com改成自己的域名
server_name mydomain.com;
ssl on;
# 證書路徑
ssl_certificate /etc/cert/fullchain.pem;
# 密鑰對路徑
ssl_certificate_key /etc/cert/privkey.pem;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;
location / {
#文件夾
root /usr/local/service/ROOT;
#主頁文件
index index.html;
}
}
server{
listen 80;
server_name mydomain.com;
rewrite ^/(.*)$ https://mydomain.com:443/$1 permanent;
}
}
1.2.2 Apache
vim /etc/apache2/sites-available/default-ssl.conf
<VirtualHost _default_:443>
DocumentRoot /var/www/html
ServerName www.mydomain.com
# 開啟SSL
SSLEngine on
SSLCertificateFile /etc/cert/fullchain.pem;
SSLCertificateKeyFile /etc/cert/privkey.pem
</VirtualHost>
3. 測試https
1.3.1 使用curl
curl "https://www.csdn.net" --verbose | head
1.3.2 使用Chrome開發者工具
1.3.3 301重定向
在遷移老的網站,為了讓http頁面能訪問到,可以設置301重定向,將http轉向https。POST請求不支持301重定向。
1.3.4 HSTS
一種新的Web安全協議HTTP Strict Transport Security(HSTS),在server的http的head里加:
Strict-Transport-Security: max-age=31536000; includeSubDomains
在接下來的31536000秒內,瀏覽器向域名和子域名的http請求強制轉成https。當發現自簽名證書時,瀏覽器會強上停止訪問,不會出現讓用戶選擇信任或不信任的彈出窗口。
1.3.5 CSP
CSP指的是內容安全策略,為了緩解很大一部分潛在的跨站腳本問題,瀏覽器的擴展程序系統引入了內容安全策略(CSP)的一般概念。CSP主要以白名單機制對網站加載或執行的資源起作用。
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';">
二、PKI
Public Key Infrastructure(PKI),中文公鑰基礎設施,由一系列實體組成的集合體,用于向客戶端提供可信的服務器身份認證。
X.509
PKI的標準規定PKI的設計、實施和運營,PKI事實上的標準是X.509。
X.509來自于國際電信聯盟電信標準(ITU-T)的X.500標準,發展主要歷史:
- X.209 1988
- X.500 1993,ISO組織接受的目錄服務系統標準,定義了一個機構如何在全局范圍內共享其名字和與之相關的對象。X.500是分層次的,其中的管理域(機構、分支、部門和工作組)可以提供這些域內的用戶和資源信息。在PKI體系中,X.500被用來惟一標識一個實體,該實體可以是機構、組織、個人或一臺服務器。X.500被認為是實現目錄服務的最佳途徑,但X.500的實現需要較大的投資,并且比其他方式速度慢;而其優勢具有信息模型、多功能和開放性。
- X.509 1993 由國際電信聯盟(ITU-T)制定的數字證書標準,最初版本公布于1988年。X.509證書由用戶公共密鑰和用戶標識符組成。此外還包括版本號、證書序列號、CA標識符、簽名算法標識、簽發者名稱、證書有效期等信息。這一標準的最新版本是X.509 v3。
三、證書
對HTTPS通訊來說,核心是理解證書。證書主要包括:簽名、服務器實體信息、CA機構信息。
1. ASN.1
ASN.1是數據結構描述語言,由ITU-T定義的標準,用來結構化描述證書。它有兩部分:
- ISO 8824/ITU X.208 描述信息內的數據、數據類型及序列格式,也就是數據的語法;
- ISO 8825/ITU X.209 描述如何將各部分數據組成消息,也就是數據的基本編碼規則。
X.509定義了證書應該包含的內容,而ASN.1是具體的數據結構。
ASN.1 原來是X.409的一部分,后來獨立出來成為一個標準 ,廣泛應用于計算機通訊領域。
2. 證書結構
3.2.1 證書的主要結構:
Certificate ::= SEQUENCE {
tbsCertificate TBSCertificate,
signatureAlgorithm AlgorithmIdentifier, # 簽名算法
signature BIT STRING # 簽名值
}
SEQUENCE是ASN.1中的一個結構體,包括多個屬性。屬性還可以嵌套其它的ASN.1結構。TBSCertificate就是一個SEQUENCE結構。
3.2.2. TBSCertificate結構:
TBSCertificate ::= SEQUENCE {
version [0] EXPLICIT Version DEFAULT v1, -- 證書版本號
serialNumber CertificateSerialNumber, -- 證書序列號,對同一CA所頒發的證書,序列號唯一標識證書
signature AlgorithmIdentifier, --證書簽名算法標識
issuer Name, --證書發行者名稱,簡稱DN
validity Validity, --證書有效期
subject Name, --證書主體名稱
subjectPublicKeyInfo SubjectPublicKeyInfo,--證書公鑰
issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, -- 證書發行者ID(可選),只在證書版本2、3中才有
subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, -- 證書主體ID(可選),只在證書版本2、3中才有
extensions [3] EXPLICIT Extensions OPTIONAL -- 證書擴展段(可選),只在證書版本3中才有
}
3.2.3 簽名算法
簽名算法標識符AlgorithmIdentifier類型也是一個SEQUENCE結構,由兩個屬性構成:
AlgorithmIdentifier ::= SEQUENCE {
algorithm OBJECT IDENTIFIER,
parameters ANY DEFINED BY algorithm OPTIONAL
}
3.2.4 issuer 示例
Let’s Encrypt:C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
3.2.5 validity
有效期,結構:
Validity ::= SEQUENCE{
notBefore Time,
notAfter Time
}
3. CSR
服務器實體為了證明自己的身份,要向CA機構申請證書。在申請之前,先生成一個CSR(Certificate Signing Request)文件,即證書簽名請求文件,把這個CSR文件發給CA機構。CA機構使用其根證書私鑰簽名就生成了證書公鑰文件,也就是頒發給用戶的證書。
CSR文件包括兩部分:
- 生成證書必須的信息,如域名、公鑰
- 服務器實體的證明材料
3.3.1 CSR也采用ASN.1標準描述,整體格式是:
CertificationRequest ::= SEQUENCE {
certificationRequestInfo CertificationRequestInfo, # 證書的請求信息
signatureAlgorithm AlgorithmIdentifier, # 簽名算法
signature BIT STRING # 簽名信息
}
3.3.2 CertificationRequestInfo結構:
CertificationRequestInfo ::= SEQUENCE{
version INTEGER { v1(0) } (v1,...),
subject Name,
subjectPKInfo SubjectPublicKeyInfo,
attributes [0] Attributes
}
- version: 表示 PKCS#10 標準的版本號;
- subject : 表示服務器主體的可分辨名稱DN,最重要的是CN值,表示證書需要包含的域名,可以包含多個;
- subjectPKInfo: 服務器密鑰對的公鑰,可以是RSA公鑰或ECDSA公鑰。服務器主體使用該密鑰對的私鑰對certificationRequestInfo進行數字簽名最終生成CSR文件。
3.3.3 CSR生成過程
- 服務器主體生成一對密鑰對,如RSA密鑰對;
- 生成CertificationRequestInfo結構體,主要包含域名、公鑰;
- 使用私鑰對CertificationRequestInfo進行數字簽名得到簽名值;
- 組合CertificationRequestInfo信息和簽名得到最終的CSR文件。
3.3.4 證書擴展
擴展有標準和非標準兩種,每個擴展都是一個OLD ASN.1結構。每個擴展都有一個critical屬性,如果該屬性值為true,CA必須嚴格處理。
3.3.5 證書分類
根據驗證模式分類
- DV(Domain Validated)證書:最常見的一種證書類型,CSR包含域名信息,CA檢驗域名所有權,如果通過審核,申請者就有權申請該域名的證書。校驗方式有DNS TXT記錄方式、服務器放置特殊文件方式。
- OV(Organization Validated)證書:CA機構對申請者的身份進行嚴格的審核,確保申請者的身份是真實的。申請時間比DV證書要長。
- EV(Extended Validation)證書:對申請者進行更嚴格的審核。
根據域名分類
- 單域名證書
- 泛域名證書
- SAN(Subject Alternative Names)證書,可以把多個不同的注冊域名合并到一張證書。
- SAN泛域名證書。
四、 證書鏈
1. 證書類型
如在Chrome中看CSDN的證書:
- 服務器實體在配置HTTPS的時候,不只是配置服務器實體證書,還涉及其它證書;
- 證書鏈的理解:
- DigiCert信任了GeoTrust RSA CA 2018
- GeoTrust RSA CA 2018信任了*.csdn.net
上面證書類型分為了:
- 服務器實體證書
- 中間證書
- 根證書:自簽名證書,位于證書鏈中的最頂端。
在使用Certbot客戶端工具生成的證書中,fullchain.pem包含了cert.pem和chain.pem文件的內容,構成了完整的證書鏈。cert.pem在fullchain.pem文件的最頂端。根證書預嵌入到了瀏覽器中,配置Nginx和Apache的時候,只需要fullchain.pem,不需要包含根證書。
2. 信任鏈校驗
- 瀏覽器連接至一個https網站
- 服務器發完整證書給瀏覽器,如fullchain.pem。對X.509標準來說,服務器應該發送完整的證書鏈(不包含根證書)。如果發送的證書不完整,客戶端可以找到所有的證書鏈,但有的瀏覽器可能不會這樣做,造成不兼容。
通過服務器實體證書找到完整證書鏈的方法,從中解析CA密鑰標識符,進而獲取上一級中間證書文件,通過中間證書的CA密鑰標識符繼續向上找到根證書。 - 校驗證書鏈關系
瀏覽器要信任每張證書,必須確保每個證書(除了根證書)的簽發者都是它的上一級證書的使用者(subject)。如果不符合,證書校驗就會失敗。
3. 根證書
linux各個發行版中,OpenSSL庫會集成根證書
openssl version -a
windows
在HKEY_CURRENT_USER注冊表管理根證書
Mozilla
在NSS底層獨立維護了可信任的根證書庫。
五、CRL 證書吊銷列表
CRL(Certificate Revocation List),是PKI技術的重要組成部分。CRL是TLS/SSL協議的一部分,X.509 V2 標準定義了CRL的語法和語義信息,CRL結構類似于證書,也使用ASN.1 結構來解釋其含義。
六、OCSP
CRL正逐步被OCSP替代(在線證書狀態協議,Online Certificate Status Protocol),定義在RF6960文檔中,主要目的是為了替換CRL,更好地核實證書的使用。
七、證書格式
1. DER
ASN.1是一種抽象的數據結構,描述了復雜的對象。證書本質是一個文件,要通過一個規則把ASN.1轉換為二進制文件。 在X.509證書中,使用的編碼方式是 Distinguished Encoding Rules(DER)。
2. BER
Basic Encoding Rules(BER)是DER的一個子集。
3. CER
CER是另一種編碼標準,用來編碼ASN.1結構
4. PEM
DER是個二進制文件,為了方便傳輸,可以將DER轉換為PEM(Privacy enhanced Electronic mail)格式。 PEM是Base64編碼方式,以:-----BEGIN CERTIFICATE----- 開頭,-----END CERTIFICATE----- 結尾。
5. 編碼轉換
PEM轉為DER
openssl x509 -in cert.pem -out cert.der -outform DER
DER轉為PEM
openssl x509 -incert.der -inform DER -out cert.pem -outform PEM
1
6. 其它的證書格式
7.6.1 PKCS#12(后綴.pkcs12 .pfx .p12)
非對稱加密的一種格式,微軟推出。PKCS#12把證書和密鑰對打包成一個文件,還可以再對文件進行加密保護。通過OpenSSL pkcs12子命令將密鑰對(privkey.pem)、服務器實體證書(cert.pem)、中間證書(chain.pem)轉換成一個文件:
openssl pkcs12 -export -out cert.pfx
-inkey privkey.pem -in cert.pem -certfile chain.pem
生成 cert.pfx時會提示進行口令保護。可以再使用命令從pfx中再導出密鑰對和證書:
# 導出密鑰對
openssl pkcs12 -in cert.pfx -nodes -nocerts -out new_privkey.pem
# 導出服務器實體證書
openssl pkcs12 -in cert.pfx -nodes -clcerts -out new_cert.pem
# 導出中間證書
openssl pkcs12 -in cert.pfx -nodes -cacerts -out new_chain.pem
7.6.2 PKCS#7
主要用來進行數字簽名和數據加密,文件后綴一般是.p7b或.p7c,使用OpenSSL crl2pkcs7進行操作。
# 生成 cert.p7b
openssl crl2pkcs7 -nocrl -certfile cert.pem -certfile chain.pem -out cert.p7b
# 導出完整證書鏈文件,服務器實體證書在文件頂部,中間證書在文件底部
openssl pkcs7 -print_certs -in cert.p7b -out fullchain.cer
7.6.3 BKS
BouncyCastleProvider,它使用的也是TripleDES來保護密鑰庫中的Key,它能夠防止證書庫被不小心修改(Keystore的keyentry改掉1個bit都會產生錯誤),BKS能夠跟JKS互操作。由于Android/ target=_blank class=infotextkey>安卓無法直接支持jks的證書庫,在安卓下一般需要使用BKS類型證書。
7. CSR管理
7.7.1 查看CSR
前面使用OpenSSL命令生成了CSR文件 , 下面使用命令查看CSR文件內容:
openssl req -in mykey_csr.pem -noout -text
其中:
- Subject Public Key Info : 生成的公鑰,包含了e和n等RSA信息
- Signature Algorithm 表示簽名算法和簽名值。
7.7.2 校驗CSR簽名
openssl req -in myreq.pem -noout -verify -key mykey_csr.pem
八、導入根證書
更新根證書庫,一般原因:
- 有新成立了一個CA機構,要導入到根證書庫中
- 自簽名了一個證書,要導入根證書庫
- 系統根證書庫太舊
Linux下 命令行update-ca-certificates可以用來同步證書。
windows下可以雙擊.cer文件彈出安裝證書界面。
本文沒有使用keytool工具,后面會使用keytool工具進行測試。本文學習資源來源:《深入淺出HTTPS從原理到實戰》 電子工業出版社 虞衛東著。感謝原作者。