使用 OpenSSL 建立私有 CA:2 中間證書

OpenSSL 建立私有 CA 三部曲:
使用 OpenSSL 建立私有 CA:1 根證書
使用 OpenSSL 建立私有 CA:2 中間證書
使用 OpenSSL 建立私有 CA:3 用戶證書html

本文將在前文《使用 OpenSSL 建立私有 CA:1 根證書》的基礎上介紹如何爲私有 CA 建立中間證書。
說明:本系列文章的演示環境爲 Ubuntu 18.04,OpenSSL 的版本爲 1.1.0g。linux

爲何要建立中間證書?

使用 CA 的根證書是能夠直接簽發用戶證書的,那麼爲何還還要建立中間證書呢?
大概有兩個緣由:git

  • 安全性
  • 創建中間證書頒發機構(CA)

先說安全性,經過簽發中間證書,再用中間證書籤發用戶證書的方式,能夠最大程度的減小更證書的使用頻率,甚至能夠離線保存根證書。若是發現中間證書被破壞,還能夠吊銷該中間證書並頒發新的中間證書。
再來講說中間證書頒發機構(CA),一箇中間證書頒發機構(CA)是一個實體,它具備根 CA 頒發的中間證書,而且能夠表明根 CA 頒發用戶證書,從而造成一條被信任的證書鏈。
這裏有必要介紹下證書產業的基本玩法:首先根證書的全部者(大的證書廠商)會和 OS 廠商合做,讓 OS 等環境默認信任本身的根證書。而後根證書的全部者會簽發中間證書賣給小一些的證書廠商。這些小的證書廠商再用中間證書建立最終證書賣給普通消費者。
舉個例子,像咱們經常使用的 Windows 操做系統默認就信任了不少廠商的根證書,好比 VeriSign 的證書,而且這些證書還會隨着 Windows 系統的更新而更新:web

上圖中,VeriSign 是根證書全部者,你安裝 windows 操做系統時,VeriSign 的根證書就被安裝到信任列表中了。Symantec Class 3 SHA256 Code Signing CA 則是 Symantec 公司從 VeriSign 公司購買的中間證書。GrapeCity inc. 則是 GrapeCity 公司從 Symantec 公司購買的最終證書用來對產品進行簽名。固然,有時候根證書廠商好比 VeriSign 等也會直接向最終用戶銷售證書。數據庫

爲了模擬中間證書頒發機構(CA),本文將使用前文中建立的根證書建立一個名稱爲 power 的中間證書。windows

準備中間 CA 的配置文件

建立文件配置文件 powerca/powerca.cnf,編輯其內容以下:瀏覽器

# OpenSSL root CA configuration file.
# v1
[ ca ]
# `man ca`
default_ca = CA_default
[ CA_default ]
# Directory and file locations.
dir = /home/nick/projects/myca/powerca
certs = $dir/certs
crl_dir = $dir/crl
new_certs_dir = $dir/newcerts
database = $dir/db/index
serial = $dir/db/serial
RANDFILE = $dir/private/random
# The root key and root certificate.
private_key = $dir/private/powerca.key.pem
certificate = $dir/certs/powerca.cert.pem
# For certificate revocation lists.
crlnumber = $dir/db/crlnumber
crl = $dir/crl/powerca.crl.pem
crl_extensions = crl_ext
default_crl_days = 30
# SHA-1 is deprecated, so use SHA-2 instead.
default_md = sha256
name_opt = ca_default
cert_opt = ca_default
default_days = 3750
copy_extensions = copy
preserve = no
policy = policy_loose
[ policy_loose ]
# Allow the intermediate CA to sign a more diverse range of certificates.
# See the POLICY FORMAT section of the `ca` man page.
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ req ]
# Options for the `req` tool (`man req`).
# Optionally, specify some defaults.
prompt = no
input_password = 123456
default_bits = 2048
distinguished_name = req_distinguished_name
string_mask = utf8only
# SHA-1 is deprecated, so use SHA-2 instead.
default_md = sha256
# Extension to add when the -x509 option is used.
# make sure use x509_extensions, do not use req_extensions.
x509_extensions = v3_ca
# use the req_extensions not work.
#req_extensions = v3_ca
[ req_distinguished_name ]
# See <https://en.wikipedia.org/wiki/Certificate_signing_request>.
countryName = CN
stateOrProvinceName = ShaanXi
localityName = Xian
organizationName = NickLi Ltd
organizationalUnitName = NickLi Ltd CA
commonName = NickLi Power CA
emailAddress = ljfpower@163.com
[ v3_ca ]
# Extensions for a typical CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ v3_intermediate_ca ]
# Extensions for a typical intermediate CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ usr_cert ]
# Extensions for client certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = client, email
nsComment = "OpenSSL Generated Client Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, emailProtection
[ server_cert ]
# Extensions for server certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = server
nsComment = "OpenSSL Generated Server Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
[ crl_ext ]
# Extension for CRLs (`man x509v3_config`).
authorityKeyIdentifier=keyid:always
[ ocsp ]
# Extension for OCSP signing certificates (`man ocsp`).
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, digitalSignature
extendedKeyUsage = critical, OCSPSigning

這個配置文件的內容和 rootca/rootca.cnf 有不少相同之處,下面是一些比較重要的不一樣之處:安全

[ CA_default ]
dir             = /home/nick/projects/myca/powerca
private_key     = $dir/private/powerca.key.pem
certificate     = $dir/certs/powerca.cert.pem
crl             = $dir/crl/powerca.crl.pem
policy          = policy_loose
[ req_distinguished_name ]
commonName = NickLi Power CA 

CA_default 中的變化主要是告訴 OpenSSL 相關文件的路徑,而中間證書的 commonName 必須不一樣於根證書。bash

準備目錄和文件

與 rootca 目錄相同,咱們須要在 powerca 目錄下建立以下的目錄和文件:dom

powerca/certs/
powerca/db/
powerca/private/
powerca/crl/
powerca/csr/
powerca/newcerts/

powerca/db/index
powerca/db/serial
powerca/db/crlnumber

其中的 powerca/private 目錄需一樣要 700 的權限,咱們使用下面的腳原本建立這些目錄和文件:

#!/bin/bash

# create dir certs db private crl csr newcerts under powerca dir.
if [ ! -d powerca/certs ]; then
    mkdir -p powerca/certs
fi

if [ ! -d powerca/db ]; then
    mkdir -p powerca/db
    touch powerca/db/index
    openssl rand -hex 16 > powerca/db/serial
    echo 1001 > powerca/db/crlnumber
fi

if [ ! -d powerca/private ]; then
    mkdir -p powerca/private
    chmod 700 powerca/private
fi

if [ ! -d powerca/crl ]; then
    mkdir -p powerca/crl
fi

if [ ! -d powerca/newcerts ]; then
    mkdir -p powerca/newcerts
fi

if [ ! -d powerca/csr ]; then
    mkdir -p powerca/csr
fi

把上面的代碼保存到 myca/powerhelper.sh 文件中,而後 cd 到 myca 目錄下執行:

$ ./powerhelper.sh

此時當前目錄爲 myca,powerca 下的子目錄和文件都已經建立成功。

建立中間證書的祕鑰

進入 powerca 目錄:

$ cd powerca 

執行下面的命令重建私鑰:

$ openssl genrsa -aes256 -out powerca/private/powerca.key.pem 4096

這裏筆者設置的密碼爲:123456,記住這個密碼,後面還會用到。而後爲了確保安全,把祕鑰的權限設置爲 400:

$ chmod 400 private/powerca.key.pem

此時當前目錄爲 myca/powerca。

建立 Certificate Signing Requests(csr)

要建立中間證書,須要使用帶有 v3_intermediate_ca 擴展名的根 CA 來簽署中間 CSR,其中 v3_intermediate_ca 擴展的配置信息就在 powerca/powerca.cnf 中:

[ v3_intermediate_ca ]
# Extensions for a typical intermediate CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, digitalSignature, cRLSign, keyCertSign

如今直接建立 csr 就好了:

$ openssl req -new \
    -config powerca.cnf \
    -sha256 \
    -key private/powerca.key.pem \
    -out csr/powerca.csr.pem

下面的命令能夠檢查生成的 csr:

$ openssl req -text -noout -in csr/powerca.csr.pem

注意,csr 中包含了 CA 的基本信息,和公鑰信息。

建立中間證書

下面是整個過程當中最爲關鍵的地方!經過 Root CA 的信息和用戶的 csr 爲用戶生成證書。
建立中間證書須要用到 rootca/rootca.cnf 中的配置信息,因此先進入 myca 目錄:

# 從 powerca 目錄回到 myca 目錄
$ cd ..      
$ openssl ca -config rootca/rootca.cnf \
    -extensions v3_intermediate_ca \
    -days 3650 -notext -md sha256 \
    -in powerca/csr/powerca.csr.pem \
    -out powerca/certs/powerca.cert.pem

在交互式的提示中輸入私鑰的密碼 123456,並贊成其它的確認提示,就完成了根證書的生成操做:

rootca/db/index 文件是 OpenSSL CA 工具存儲證書的數據庫,請不要手動修改這個文件(除非你清楚的知道本身在幹什麼)。此時它應該包含了根證書和中間證書的信息:

證書生成後咱們把它的權限修改成 444:

$ chmod 444 powerca/certs/powerca.cert.pem

驗證中間證書

經過下面的命令驗證中間證書:

$ openssl x509 -noout -text -in powerca/certs/powerca.cert.pem

在中間證書中,Subject 的 Common Name 爲 "NickLi Power CA",而 Issuer 的 Common Name 爲 "NickLi Root CA"。
還能夠經過下面的命令來檢查中間證書的狀態:

$ openssl verify -CAfile rootca/certs/rootca.cert.pem powerca/certs/powerca.cert.pem

建立證書鏈文件

當 web 瀏覽器等應用程序試圖驗證中間 CA 頒發的證書時,它還必須根據根證書驗證中間證書。這就須要構建完整的證書信任鏈供應用程序驗證。所謂的證書鏈,簡單的說就是把根證書和中間證書按照順序放置在同一個證書文件中。重點是:中間證書在上面,根證書在下面。好比爲咱們的中間證書建立證書鏈:

$ cat powerca/certs/powerca.cert.pem \
      rootca/certs/rootca.cert.pem > powerca/certs/powerca-chain.cert.pem
$ chmod 444 powerca/certs/powerca-chain.cert.pem

注意:在局域網環境中,咱們通常會把生成的這個證書鏈安裝到用戶的機器上。

pem 格式的證書、證書鏈文件適用的場景比較多,可是在 windows 系統中通常使用 p12 格式,因此咱們還須要建立一個 p12 格式的證書鏈:

$ openssl pkcs12 -export \
    -name "powerca chain" \
    -inkey powerca/private/powerca.key.pem \
    -in powerca/certs/powerca.cert.pem \
    -certfile powerca/certs/powerca-chain.cert.pem \
    -out powerca/certs/powerca-chain.cert.p12

這個過程當中須要輸入私鑰 powerca/private/powerca.key.pem 的密碼(這裏是 123456),而且爲新證書設置的密碼。

總結

如今咱們已經有了私有 CA 的根證書而且生成了中間證書和證書鏈,在接下來的《使用 OpenSSL 建立私有 CA:3 用戶證書》一文中咱們將詳細的介紹如何使用中間證書建立用戶證書,以及如何把證書部署到 web 站點和客戶端。

參考:
OpenSSL Certificate Authority
《openssl-cookbook》

相關文章
相關標籤/搜索