OpenSSL-證書鏈

    SSL的CA證書可分爲兩種:Root CA(根CA證書)和Intermediate CA(中間CA證書)。其中Root CA是信任錨點,一條證書鏈中只能有一個。Intermediate CA可以有多個。Root CA通常不直接簽發用戶證書,而是簽發Intermediate CA,由Intermediate CA來簽發終用戶書。它們之間的關係如下圖所示:


    證書鏈就是Root CA簽發二級Intermediate CA,二級Intermediate CA可以簽發三級Intermediate CA,也可以直接簽發用戶證書。從Root CA到用戶證書之間構成了一個信任鏈:信任Root CA,就應該信任它所信任的二級Intermediate CA,從而就應該信任三級Intermediate CA直至信任用戶證書。

    客戶的系統或瀏覽器上會默認安裝多個知名的Root CA,在SSL Handshake過程中Server需要將證書鏈發送給Client(通常是瀏覽器),Client使用Root CA逐級對證書進行驗證,直至驗證Server的用戶證書。

證書鏈的製作腳本如下:
#!/bin/bash

set -e
dir=`dirname $0`
key_bits=2048
expire_days=3650
subj=/C="CN"/ST="Liaoning"/L="Shenyang"/O="Dove"/OU="dove"/CN="doveR"
subji=/C="CN"/ST="Liaoning"/L="Shenyang"/O="Dove"/OU="dove"/CN="doveI"
subjs=/C="CN"/ST="Liaoning"/L="Shenyang"/O="Dove"/OU="dove"/CN="doveS"
subj2=/C="CN"/ST="Liaoning"/L="Shenyang"/O="DoveCERT"/OU="dove"/CN="dove"
server="server-chain"
param=$server
if [ -d $param ]; then
    rm -r $param
fi
mkdir -p $param
cd $param
ca_name=ca-root-$param
root_cacer=$ca_name.cer
root_cakey=$ca_name.key
ca_name=ca-sub1-$param
sub1_cacer=$ca_name.cer
sub1_cakey=$ca_name.key
ca_name=ca-sub2-$param
cacer=$ca_name.cer
cakey=$ca_name.key
cer=$param.cer
csr=$param.csr
key=$param.key

mkdir -p $dir/demoCA/{private,newcerts}
touch $dir/demoCA/index.txt
echo 02 > $dir/demoCA/serial
cd demoCA
ln -sf ../$root_cacer cacert.pem
cd -
cd demoCA/private
ln -sf ../../$root_cakey cakey.pem
cd -
#Root CA
openssl genrsa -out $root_cakey $key_bits
openssl req -x509 -newkey rsa:$key_bits -keyout $root_cakey -nodes -out $root_cacer -subj $subj -days $expire_days
echo "===================Gen Root CA OK===================="

#Sub1 CA
openssl genrsa -out $sub1_cakey $key_bits
openssl req -new -key $sub1_cakey -sha256 -out $csr -subj $subji -days $expire_days
openssl ca -extensions v3_ca -batch -notext -in $csr -out $sub1_cacer
echo "===================Gen Sub1 CA OK===================="

#Sub2 CA
openssl genrsa -out $cakey $key_bits
openssl req -new -key $cakey -sha256 -out $csr -subj $subjs -days $expire_days
openssl ca -extensions v3_ca -batch -notext -in $csr -out $cacer -cert $sub1_cacer -keyfile $sub1_cakey

echo "===================Gen Sub2 CA OK===================="

#Server cert
openssl genrsa -out $key $key_bits
openssl req -new -key $key -sha256 -out $csr -subj $subj2 -days $expire_days
openssl x509 -req -in $csr -sha256 -out $cer -CA $cacer -CAkey $cakey -CAserial t_ssl_ca.srl -CAcreateserial -days $expire_days -extensions v3_req
#openssl pkcs12 -export -clcerts -in client.cer -inkey client.key -out client.p12
rm -f *.csr *.srl

cat $cer $cacer $sub1_cacer |tee $param.pem
echo "===================Gen All OK===================="

   

    在Handshake過程中Server會按照$param.pem文件中的順序發送證書鏈。Client在收到證書鏈的時候會先驗證用戶證書,但無法找到發行者(Issuer),然後會遍歷證書鏈找到Issuer,再找到Issuer的Issuer,直到能用Root CA進行驗證,從而完成了整個證書鏈的驗證。

    【注1】:生成最後的證書($param.pem)時一定要按照順序先添加用戶證書($cer),再追加Intermediate CA證書($cacer,$sub1_cacer),否則在Server端(如:nginx)會載入失敗,因爲nginx會使用第一個證書與私鑰進行匹配。

    【注2】:如果Client用OpenSSL API驗證Server的證書鏈,則需要通過SSL_CTX_set_verify_depth(ctx, 3)將驗證深度設置爲3(如果Root CA以下共有3級證書)。如果是Client是瀏覽器則只要安裝了Root CA證書即可。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章