細說 CA 和證書
CA,Catificate Authority,它的作用就是提供證照(即伺服器證照,由域名、公司資訊、序列號和簽名資訊組成)加強服務端和客戶端之間資訊互動的安全性,以及證照運維相關服務。任何個體/組織都可以扮演 CA 的角色,只不過難以得到客戶端的信任,能夠受瀏覽器預設信任的 CA 大廠商有很多,其中 TOP5 是 Symantec、Comodo、Godaddy、GolbalSign 和 Digicert。
伺服器證照分類
可以通過兩個維度來分類,一個是商業角度,一個是業務角度。
單域名 | 多域名 | 泛域名 | 多泛域名 | |
---|---|---|---|---|
DV | 支援 | 不支援 | ||
OV | 支援 | |||
EV | 支援 | 不支援 | ||
舉例 | www.barretlee.com | www.barretlee.com www.xiaohuzige.com www.barret.cc |
*.barretlee.com | *.barretlee.com *.xiaohuzige.com *.barret.cc |
需要強調的是,不論是 DV、OV 還是 EV 證照,其加密效果都是一樣的! 它們的區別在於:
- DV(Domain Validation),面向個體使用者,安全體系相對較弱,驗證方式就是向 whois 資訊中的郵箱傳送郵件,按照郵件內容進行驗證即可通過;
- OV(Organization Validation),面向企業使用者,證照在 DV 證照驗證的基礎上,還需要公司的授權,CA 通過撥打資訊庫中公司的電話來確認;
- EV(Extended Validation),開啟 Github 的網頁,你會看到 URL 位址列展示了註冊公司的資訊,這會讓使用者產生更大的信任,這類證照的申請除了以上兩個確認外,還需要公司提供金融機構的開戶許可證,要求十分嚴格。
OV 和 EV 證照相當昂貴,使用方可以為這些頒發出來的證照買保險,一旦 CA 提供的證照出現問題,一張證照的賠償金可以達到 100w 刀以上。
CA 的作用
前文 HTTPS證照生成原理和部署細節 提到如果本地生成公/私鑰對和對應未簽證的證照,如果使用的證照沒有簽證,或者未在瀏覽器受信的 CA 簽證,你會看到下圖的問題:
上圖出現的錯誤是 net:ERR_CERT_AUTHORITY_INVALID
,我們生成證照和公/私鑰對的流程都是正確的,但是瀏覽器不認這張證照,並且提示證照授權不通過;如果通過其他與 Common Name 不同的域名去訪問,如我註冊的時候使用的 localhost
,但是訪問的時候用的 127.0.0.1
,還會報出這樣的錯誤:
錯誤碼為 net:ERR_CERT_COMMON_NAME_INVALID
,意思是 Common Name 不匹配,具體校驗流程可以在瀏覽器的 DevTools 中看到:
從上面幾張圖,可以大致瞭解 CA 和證照會做哪些事情,證照由域名、公司資訊、序列號和簽名資訊組成,當我們通過 HTTPS 訪問頁面時,瀏覽器會主動驗證證照資訊是否匹配,也會驗證證照是否有效。
CA 有權給所有的域名簽發證照,如它可以私自給我的網站簽發一張 www.barretlee.com
的證照,並且可以拿著新證照攔截網頁流量(當然,前提是這個 CA 是瀏覽器認證的權威 CA),那我的網站可能就很不安全了,對擁新證照的人來說,我的網站等同於在 HTTP 下進行通訊。
評估 CA 供應商
CA 供應商很多,提供服務的側重點可能也存在一些差異,比如很多 CA 都沒有提供證照吊銷的服務,這一點對於安全性要求很高的企業來說是完全不能接受的,那麼對 CA 供應商的評估需要注意寫什麼呢?
1. 內建根
所謂內建根,就是 CA 的根證照內建到各種通用的系統/瀏覽器中,只有根證照的相容性夠強,它所能覆蓋的瀏覽器才會越多。
2. 安全體系
兩個指標可以判斷 CA 供應商是否靠譜,一是看價格,價格高自然有它的理由,必然提供了全套的安全保障體系;二是看黑歷史,該 CA 供應商有沒有爆出過什麼漏洞,比如之前的 DigiNotar,被伊朗入侵,簽發了 500 多張未授權的證照,結果直接被各系統/瀏覽器將其根拉入黑名單,毫無疑問公司直接倒閉。
3. 核心功能和擴充套件功能
這就需要從業務上考慮了,不同的規模的企業、不同的業務對證照的要求不一樣,比如證照是否會考慮無 SNI 支援的瀏覽器問題,是否支援在 reissue 的時候新增域名,是否支援 CAA,是否支援短週期證照等等。
4. 價格
企業完全沒必要購買 Github 那樣的 EV 證照,太昂貴,而且一般的企業也未必能夠申請到這樣的證照。供應商很大,價格可以好好評估下,不一定要最貴,最適合的就行。
自建 Root CA
OpenSSL 是一個免費開源的庫,它提供了構建數字證照的命令列工具,其中一些可以用來自建 Root CA。
很多網站都希望使用者知道他們建立的網路通道是安全的,所以會想 CA 機構購買證照來驗證 domain,所以我們也可以在很多 HTTPS 的網頁位址列看到一把小綠鎖。
然而在一些情況下,我們沒必要去 CA 機構購買證照,比如在內網的測試環境中,為了驗證 HTTPS 下的一些問題,我們不需要部署昂貴的證照,這個時候自建 Root CA,給自己頒發證照就顯得很有價值了。
本節內容較多,主要是程式碼演示生成證照和驗證的過程,可以跳過看下一節,直接看 這裡:
git clone https://github.com/barretlee/autocreate-ca.git
- 依次執行
install-rootCA.sh
、install-intermediateCA.sh
和install-websiteConfig.sh
首先找到一個放置證照的資料夾,比如 /root/ca
下,下方的測試也在改目錄下,如果你要更換其他目錄,記得替換下文中的目錄地址。
建立 root pair
扮演 CA 角色,就意味著要管理大量的 pair 對,而原始的一對 pair 對叫做 root pair,它包含了 root key(ca.key.pen
)和 root certificate(ca.cert.pem
)。通常情況下,root CA 不會直接為伺服器或者客戶端簽證,它們會先為自己生成幾個中間 CA(intermediate CAs),這幾個中間 CA 作為 root CA 的代表為伺服器和客戶端簽證。
注意:一定要在絕對安全的環境下建立 root pair,可以斷開網路、拔掉網線和網路卡,當然,如果是測試玩一玩就不用這麼認真了。
設定資料夾結構,並且配置好 openssl 設定:
# cd /root/ca
# mkdir certs crl newcerts private
# chmod 700 private
# touch index.txt
# echo 1000 > serial
# wget -O /root/ca/openssl.cnf \
https://raw.githubusercontent.com/barretlee/autocreate-ca/master/cnf/root-ca
建立 root key,密碼可為空,設定許可權為只可讀:
# cd /root/ca
# openssl genrsa -aes256 -out private/ca.key.pem 4096
Enter pass phrase for ca.key.pem: secretpassword
Verifying - Enter pass phrase for ca.key.pem: secretpassword
# chmod 400 private/ca.key.pem
建立 root cert,許可權設定為可讀:
# cd /root/ca
# openssl req -config openssl.cnf \
-key private/ca.key.pem \
-new -x509 -days 7300 -sha256 -extensions v3_ca \
-out certs/ca.cert.pem
Enter pass phrase for ca.key.pem: secretpassword
You are about to be asked to enter information that will be incorporated
into your certificate request.
-----
Country Name (2 letter code) [XX]:CN
State or Province Name []:Zhejiang
Locality Name []:
Organization Name []:Barret Lee
Organizational Unit Name []:Barret Lee Certificate Authority
Common Name []:Barret Lee Root CA
Email Address []:
# chmod 444 certs/ca.cert.pem
驗證證照:
# openssl x509 -noout -text -in certs/ca.cert.pem
正確的輸出應該是這樣的:
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
87:e8:c0:a0:4b:e2:12:5d
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=CN, ST=Zhejiang, O=Barret Lee, OU=Barret Lee Certificate Authority, CN=Barret Lee Root CA
Validity
Not Before: Apr 23 05:46:36 2016 GMT
Not After : Apr 18 05:46:36 2036 GMT
Subject: C=CN, ST=Zhejiang, O=Barret Lee, OU=Barret Lee Certificate Authority, CN=Barret Lee Root CA
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (4096 bit)
Modulus (4096 bit):
// ...
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Key Identifier:
E5:2D:B8:2B:DC:88:FE:CE:DA:93:D8:6F:2E:74:04:D2:39:E7:C8:03
X509v3 Authority Key Identifier:
keyid:E5:2D:B8:2B:DC:88:FE:CE:DA:93:D8:6F:2E:74:04:D2:39:E7:C8:03
X509v3 Basic Constraints: critical
CA:TRUE
X509v3 Key Usage: critical
Digital Signature, Certificate Sign, CRL Sign
Signature Algorithm: sha256WithRSAEncryption
// ...
包含:
- 數字簽名(Signature Algorithm)
- 有效時間(Validity)
- 主體(Issuer)
- 公鑰(Public Key)
- X509v3 擴充套件,openssl config 中配置了 v3_ca,所以會生成此項
建立 intermediate pair
目前我們已經擁有了 Root Pair,事實上已經可以用於證照的發放了,但是由於根證照很乾淨,特別容易被汙染,所以我們需要建立中間 pair 作為 root pair 的代理,生成過程同上,只是細節略微不一樣。
生成目錄結構和 openssl 的配置,這裡的配置是針對 intermediate pair 的:
# mkdir /root/ca/intermediate
# cd /root/ca/intermediate
# mkdir certs crl csr newcerts private
# chmod 700 private
# touch index.txt
# echo 1000 > serial
# echo 1000 > /root/ca/intermediate/crlnumber
# wget -O /root/ca/openssl.cnf \
https://raw.githubusercontent.com/barretlee/autocreate-ca/master/cnf/intermediate-ca
建立 intermediate key,密碼可為空,設定許可權為只可讀:
# cd /root/ca
# openssl genrsa -aes256 \
-out intermediate/private/intermediate.key.pem 4096
Enter pass phrase for intermediate.key.pem: secretpassword
Verifying - Enter pass phrase for intermediate.key.pem: secretpassword
# chmod 400 intermediate/private/intermediate.key.pem
建立 intermediate cert,設定許可權為只可讀,這裡需要特別注意的一點是 Common Name 不要與 root pair 的一樣 :
# cd /root/ca
# openssl req -config intermediate/openssl.cnf -new -sha256 \
-key intermediate/private/intermediate.key.pem \
-out intermediate/csr/intermediate.csr.pem
Enter pass phrase for intermediate.key.pem: secretpassword
You are about to be asked to enter information that will be incorporated
into your certificate request.
-----
Country Name (2 letter code) [XX]:CN
State or Province Name []:Zhejiang
Locality Name []:
Organization Name []:Barret Lee
Organizational Unit Name []:Barret Lee Certificate Authority
Common Name []:Barret Lee Intermediate CA
Email Address []:
使用 v3_intermediate_ca
擴充套件簽名,密碼可為空,中間 pair 的有效時間一定要為 root pair 的子集:
# cd /root/ca
# openssl ca -config openssl.cnf -extensions v3_intermediate_ca \
-days 3650 -notext -md sha256 \
-in intermediate/csr/intermediate.csr.pem \
-out intermediate/certs/intermediate.cert.pem
Enter pass phrase for ca.key.pem: secretpassword
Sign the certificate? [y/n]: y
# chmod 444 intermediate/certs/intermediate.cert.pem
此時 root 的 index.txt
中將會多出這麼一條記錄:
V 260421055318Z 1000 unknown .../CN=Barret Lee Intermediate CA
驗證中間 pair 的正確性:
# openssl x509 -noout -text \
-in intermediate/certs/intermediate.cert.pem
# openssl verify -CAfile certs/ca.cert.pem \
intermediate/certs/intermediate.cert.pem
intermediate.cert.pem: OK
瀏覽器在驗證中間證照的時候,同時也會去驗證它的上一級證照是否靠譜,建立證照鏈,將 root cert 和 intermediate cert 合併到一起,可以讓瀏覽器一併驗證:
# cat intermediate/certs/intermediate.cert.pem \
certs/ca.cert.pem > intermediate/certs/ca-chain.cert.pem
# chmod 444 intermediate/certs/ca-chain.cert.pem
建立伺服器/客戶端證照
終於到了這一步,生成我們伺服器上需要部署的內容,上面已經解釋了為啥需要建立中間證照。root pair 和 intermediate pair 使用的都是 4096 位的加密方式,一般情況下伺服器/客戶端證照的過期時間為一年,所以可以安全地使用 2048 位的加密方式。
# cd /root/ca
# openssl genrsa -aes256 \
-out intermediate/private/www.barretlee.com.key.pem 2048
# chmod 400 intermediate/private/www.barretlee.com.key.pem
建立 www.barretlee.com
的證照:
# cd /root/ca
# openssl req -config intermediate/openssl.cnf \
-key intermediate/private/www.barretlee.com.key.pem \
-new -sha256 -out intermediate/csr/www.barretlee.com.csr.pem
Enter pass phrase for www.barretlee.com.key.pem: secretpassword
You are about to be asked to enter information that will be incorporated
into your certificate request.
-----
Country Name (2 letter code) [XX]:CN
State or Province Name []:Zhejiang
Locality Name []:Hangzhou
Organization Name []:Barret Lee
Organizational Unit Name []:Barret Lee's Personal Website
Common Name []:www.barretlee.com
Email Address []:barret.china@gmail.com
使用 intermediate pair 簽證上面證照:
# cd /root/ca
# openssl ca -config intermediate/openssl.cnf \
-extensions server_cert -days 375 -notext -md sha256 \
-in intermediate/csr/www.barretlee.com.csr.pem \
-out intermediate/certs/www.barretlee.com.cert.pem
# chmod 444 intermediate/certs/www.barretlee.com.cert.pem
可以看到 /root/ca/intermediate/index.txt
中多了一條記錄:
V 170503055941Z 1000 unknown .../emailAddress=barret.china@gmail.com
驗證證照:
# openssl x509 -noout -text \
-in intermediate/certs/www.barretlee.com.cert.pem
# openssl verify -CAfile intermediate/certs/ca-chain.cert.pem \
intermediate/certs/www.barretlee.com.cert.pem
www.barretlee.com.cert.pem: OK
此時我們已經拿到了幾個用於部署的檔案:
ca-chain.cert.pem
www.barretlee.com.key.pem
www.barretlee.com.cert.pem
新增信任 CA 和證照的除錯
雙擊 /root/ca/intermediate/certs/ca-chain.cert.pem
將證照安裝到系統中,目的是讓本機信任這個 CA,將其當作一個權威 CA,安裝 root pem
或者 intermediate chain pem
都是可以的,它們都具備驗證能力。如果不執行這一步,瀏覽器依然會提示net:ERR_CERT_AUTHORITY_INVALID
。
上面申請測試證照時,我設定的 Common Name 為 www.barretlee.com
,由於不線上上機器測試,可以將其新增到 hosts:
127.0.0.1 www.barretlee.com
執行下方測試程式碼:
// https-server.js
var https = require('https');
var fs = require('fs');
var options = {
key: fs.readFileSync('/root/ca/intermediate/private/www.barretlee.com.key.pem'),
cert: fs.readFileSync('/root/ca/intermediate/certs/www.barretlee.com.cert.pem'),
passphrase: 'passoword' // 如果生成證照的時候設定了密碼,請新增改引數和密碼
};
https.createServer(options, function(req, res) {
res.writeHead(200);
res.end('hello world');
}).listen(8000, function(){
console.log('Open URL: https://www.barretlee.com:8000');
});
可以看到這樣的效果:
檢視證照的詳細資訊:
回到最初的問題:
然而在一些情況下,我們沒必要去 CA 機構購買證照,比如在內網的測試環境中,為了驗證 HTTPS 下的一些問題,我們不需要部署昂貴的證照,這個時候自建 Root CA,給自己頒發證照就顯得很有價值了。
一般公司內網的電腦都會強制安裝一些安全證照,此時就可以把我們自建自簽名的證照匯入/引導安裝到使用者的電腦中啦~
無 SNI 支援問題
很多公司由於業務眾多,域名也是相當多的,為了方便運維,會讓很多域名指向同樣的 ip,然後統一將流量/請求分發到後端,此時就會面臨一個問題:由於 TLS/SSL 在 HTTP 層之下,客戶端和伺服器握手的時候還拿不到 origin 欄位,所以伺服器不知道這個請求是從哪個域名過來的,而伺服器這邊每個域名都對應著一個證照,伺服器就不知道該返回哪個證照啦。
SNI 就是用來解決這個問題的,官方解釋是
SNI(Server Name Indication)是為了解決一個伺服器使用多個域名和證照的SSL/TLS擴充套件。一句話簡述它的工作原理就是,在連線到伺服器建立SSL連結之前先傳送要訪問站點的域名(Hostname),這樣伺服器根據這個域名返回一個合適的證照。
然後有將近 25% 的瀏覽器不支援該欄位的擴充套件,這個問題有兩個通用解決方案:
- 使用 VIP 伺服器,每個域名對應一個 VIP,然後 VIP 與統一接入服務對接,通過 ip 來分發證照,不過運維成本很高,可能也需要大量的 VIP 伺服器
- 採用多泛域名,將多個泛域名證照打包進一個證照,可以看看淘寶頁面的證照它的缺點是每次新增域名都需要更新證照。
幾個細節知識點
1. 證照選擇
證照有多張加密方式,不同的加密方式對 CPU 計算的損耗不同,安全級別也不同。TLS 在進行第一次握手的時候,客戶端會向伺服器端 say hello
,這個時候會告訴伺服器,它支援哪些演算法,此時伺服器可以將最適合的證照發給客戶端。
2. 證照的吊銷
CA 證照的吊銷存在兩種機制,一種是線上檢查,client 端向 CA 機構傳送請求檢查 server 公鑰的靠譜性;第二種是 client 端儲存一份 CA 提供的證照吊銷列表,定期更新。前者要求查詢伺服器具備良好效能,後者要求每次更新提供下次更新的時間,一般時差在幾天。安全性要求高的網站建議採用第一種方案。
大部分 CA 並不會提供吊銷機制(CRL/OCSP),靠譜的方案是為根證照提供中間證照,一旦中間證照的私鑰洩漏或者證照過期,可以直接吊銷中間證照並給使用者頒發新的證照。中間證照的簽證原理於上上條提到的原理一樣,中間證照還可以產生下一級中間證照,多級證照可以減少根證照的管理負擔。
很多 CA 的 OCSP Server 在國外,線上驗證時間比較長,如果可以聯絡 CA 供應商將 Server 轉移到國內,效率可以提升 10 倍左右。
3. PKI 體系
比較主流的兩種方案是 HPKP 和 Certificate Transparency:
- HPKP 就是使用者第一次訪問的時候記下 sign 資訊,以後不匹配則拒絕訪問,這存在很大的隱患,比如 Server 更新了證照,或者使用者第一次訪問的時候就被人給黑了
- Certificate Transparency 意思就是讓 CA 供應商透明化 CA 服務日誌,防止 CA 供應商偷偷簽證
小結
看了不少文章,對 CA 和證照相關的知識做了一些總結,可能不全面,也可能存在表述錯誤或者知識性錯誤,歡迎拍磚!
擴充閱讀
相關文章
- TAM和CA證書的整合
- 根證書 CA
- ca 證書機制
- CA證書伺服器(6)利用CA證書配置安全Web站點伺服器Web
- 【原】CA證書的理解
- 數字證書認證(CA)中心
- PKI/CA與數字證書
- android 安裝CA證書Android
- 配置docker和containerd,使用ca證書訪問harborDockerAI
- 基於CFSSL工具建立CA證書,服務端證書,客戶端證書服務端客戶端
- 建立和管理一個 CA 及證書的生命週期
- 細說API - 認證、授權和憑證API
- 使用 OpenSSL 建立私有 CA:1 根證書
- CA數字證書包括哪些內容?
- 使用 OpenSSL 建立私有 CA:2 中間證書
- 使用 openssl 命令列構建 CA 及證書命令列
- go-自籤ca證書,客戶端數字證書,服務端數字證書Go客戶端服務端
- ca證書怎樣理解?與恆訊科技的ssl證書一樣嗎?
- 使用 OpenSSL 建立私有 CA:3 使用者證書
- 如何在Ubuntu 20.04中配置CA根證書Ubuntu
- Docker開啟TLS和CA認證DockerTLS
- HTTPS 證書生成原理和部署細節HTTP
- 使用OpenSSL建立生成CA證書、伺服器、客戶端證書及金鑰伺服器客戶端
- 自己成為一個證書頒發機構(CA)
- https--OpenSSL生成root CA及簽發證書HTTP
- 通過Go語言建立CA與簽發證書Go
- CDN加速域名https中級CA證書的配置HTTP
- CA證書伺服器(2)非對稱式加密伺服器加密
- CA證書伺服器(1)資料加密技術伺服器加密
- 申請SSL證書CA機構的選擇很重要
- fabric-ca載入openssl生成的ecdsa標準證書
- Kubernetes客戶端認證——基於CA證書的雙向認證方式客戶端
- .pfx 證書和 .cer 證書
- CA/B 論壇10月會議 S/MIME證書和程式碼簽名證書的新基線要求提上日程
- Windows下IIS部署自建CA證書進行雙向認證的過程Windows
- TLS、SSL、CA 證書、公鑰、私鑰。。。今天捋一捋!TLS
- 中移鏈結合CA證書實現節點准入控制
- 利用IPsec實現網路安全之四(CA證書實現身份驗證)