­

創建私有CA,我就用openSSL

簡介

一般情況下我們使用的證書都是由第三方權威機構來頒發的,如果我們有一個新的https網站,我們需要申請一個世界範圍內都獲得認可的證書,這樣我們的網站才能被無障礙的訪問。

如果在某些情況下,我們的網站或者系統並不是公開的,但是也需要使用tls協議的話,那麼就需要自己搭建一個CA服務器。這樣的CA服務器就叫做private CA。

熟悉證書的朋友可能會說了,為什麼不使用自簽名證書呢?也可以達到安全通信的目的。

這是因為自簽名證書的作用比較有限,它沒有CRL和OCSP的能力,並且使用起來也不是很方便。所以我們需要一整套有效的CA簽發體系,這也是我們需要搭建private CA的目的。

搭建root CA

在搭建root CA之前我們需要創建幾個合適的目錄來保存CA的相關信息,比如我們需要一個保存證書的目錄certs,一個保存密鑰的地方keys,一個CA數據庫db。

其中db需要一個index文件,serial文件和crlnumber文件。

我們用下面的命令創建對應的文件和目錄:

mkdir certs db keys
touch db/index
openssl rand -hex 16  > db/serial
echo 1001 > db/crlnumber

目錄建好之後,我們還需要一個非常重要的root ca配置文件。後續可以根據這個配置文件來創建CA相關的信息。

一般情況下CA配置文件是不需要的,只有我們需要創建比較複雜CA的情況下才需要使用ca配置文件。

下面是一個CA配置文件的例子:

[default]
name                    = root-ca
domain_suffix           = flydean.com
default_ca              = ca_config
name_opt                = utf8,esc_ctrl,multiline,lname,align

[ca_config]
database                = db/index
serial                  = db/serial
crlnumber               = db/crlnumber
certificate             = root-ca.crt
private_key             = keys/root-ca.key
RANDFILE                = keys/random
new_certs_dir           = certs
unique_subject          = no
copy_extensions         = none
default_days            = 365
default_crl_days        = 100
default_md              = sha256
policy                  = ca_policy

[ca_policy]
countryName             = match
stateOrProvinceName     = optional
organizationName        = match
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

[req]
default_bits            = 4096
encrypt_key             = yes
default_md              = sha256
utf8                    = yes
string_mask             = utf8only
prompt                  = no
distinguished_name      = ca_dist
req_extensions          = ca_req_ext

[ca_dist]
countryName             = "CN"
organizationName        = "flydean"
commonName              = "Root CA"

[ca_req_ext]
basicConstraints        = critical,CA:true
keyUsage                = critical,keyCertSign,cRLSign
subjectKeyIdentifier    = hash

[sub_ca_ext]
authorityInfoAccess     = @issuer_info
authorityKeyIdentifier  = keyid:always
basicConstraints        = critical,CA:true,pathlen:0
crlDistributionPoints   = @crl_info
extendedKeyUsage        = clientAuth,serverAuth
keyUsage                = critical,keyCertSign,cRLSign
subjectKeyIdentifier    = hash

[crl_info]
URI.0                   = //crl3.digicert.com/DigiCertTLSRSASHA2562020CA1-4.crl

[issuer_info]
caIssuers;URI.0         = //cacerts.digicert.com/DigiCertTLSRSASHA2562020CA1-1.crt
OCSP;URI.0              = //ocsp.digicert.com

[ocsp_ext]
authorityKeyIdentifier  = keyid:always
basicConstraints        = critical,CA:false
extendedKeyUsage        = OCSPSigning
noCheck                 = yes
keyUsage                = critical,digitalSignature
subjectKeyIdentifier    = hash

生成root CA

有了上面的配置文件和目錄信息,就可以生成root CA了。

首先我們需要創建私鑰和root ca的csr文件如下:

openssl req -new -config root-ca.conf  -out root-ca.csr  -keyout keys/root-ca.key

接下來我們創建一個自簽名的證書,這裡我們需要用到配置文件中的ca_req_ext部分:

 openssl ca -selfsign  -config root-ca.conf  -in root-ca.csr   -out root-ca.crt -extensions ca_req_ext

運行該命令之後,我們會在certs文件夾中創建一個自簽名證書文件。

除此之外,還向db中的index文件中寫入了下面的內容:

V	230501041451Z		4445DE5C0285EAEF2E58757D5CB1E949	unknown	/C=CN/O=flydean/CN=Root CA

這是一個文本文件,裏面保存的是生成的證書索引,證書中的字段是通過tab來進行分割的。

第一個字段V表示valid也就是有效的意思,這個字段還可以有其他幾個值,比如R表示revoked,E表示expired。

第二個字段是過期時間,格式是YYMMDDHHMMSSZ。

第三個字段是Revocation日期,如果空表示沒有revoked。

第四個字段是序列號,也就是生成的CA名字。

第五個字段是文件的位置,unknown表示未知。

最後一個字段是這個證書的名字,用於和其他的證書做區分。

使用CRL

有了root-ca.conf之後,我們可以使用它來創建CRL:

openssl ca -gencrl  -config root-ca.conf  -out root-ca.crl

現在生成的root-ca.crl文件還沒有任何證書信息。

如果我們想要撤銷某個頒發的CA,可以使用下面的命令:

openssl ca  -config root-ca.conf  -revoke certs/torevoke.pem -crl_reason unspecified

在revoke中指定要revoke的證書即可。

這裡要注意的是我們需要指定crl_reason,crl_reason可以是下面幾個值:

unspecified
keyCompromise
CACompromise
affiliationChanged
superseded
cessationOfOperation
certificateHold
removeFromCRL

使用OSCP

對於OSCP來說,需要一個OCSP responder來響應OCSP的請求。這個OCSP responder和CA本身並不是同一個,需要單獨創建。

首先,我們創建OCSP responder的key和證書請求CSR:

openssl req -new  -newkey rsa:2048  -keyout keys/root-ocsp.key -out root-ocsp.csr

當然輸入必須的參數之後,key和CSR就可以生成了。

接下來我可以使用root CA和root-ocsp.csr頒發OCSP證書,這裡我們需要用到配置文件中的ocsp_ext部分。

openssl ca  -config root-ca.conf  -in root-ocsp.csr  -out root-ocsp.crt -extensions ocsp_ext  -days 10

上面的命令為OCSP responder生成了一個有效期為10天的證書。

有了證書,我們可以方便的搭建一個本地的OCSP responder如下所示:

openssl ocsp  -port 9000 -index db/index  -rsigner root-ocsp.crt -rkey keys/root-ocsp.key  -CA root-ca.crt  -text
Enter pass phrase for keys/root-ocsp.key:
Waiting for OCSP client connections...

這樣我們就啟動了一個OCSP服務器端。

另開一個窗口,執行下面的命令來請求OCSP:

 openssl ocsp -issuer root-ca.crt  -CAfile root-ca.crt  -cert root-ocsp.crt   -url //127.0.0.1:9000

可以得到下面的結果:

Response verify OK
root-ocsp.crt: good
	This Update: May  1 08:09:31 2022 GMT

這就說明OCSP responder搭建成功了。

這裡啟動的是一個本地服務,在正式環境中可以考慮將其遷移到單獨的服務器中。

總結

使用上面的命令,我們搭建了一個私有的CA服務,和對應的OCSP,openssl非常強大,基本上你可以用他來做任何事情。

更多內容請參考 //www.flydean.com/45-openssl-private-ca/

最通俗的解讀,最深刻的乾貨,最簡潔的教程,眾多你不

歡迎關注我的公眾號:「程序那些事」,懂技術,更懂你!