最近因為公司在建立 ISO 27001 資訊安全管理系統,在文件管理部分就會想說要有一個高強度且具備不可否認性的數位簽章(Digital Signature)。建立一組公司用的 CA 憑證並透過這張 CA 憑證簽發給員工使用的數位憑證其實很簡單,但之前一直沒機會研究如何手工打造 CRL 憑證撤銷清單,今天研究了一下,終於可以自行簽發 CRL 憑證了。
Big Picture
由於手工打造 PKI 基礎建設牽涉到的知識相對複雜,這邊我試圖用比較簡單的方式來說明。
-
首先,你需要先建立一個最上層、最權威的「受信任的根憑證」(Trusted Root Certification Authorities)
以下簡稱 CA 憑證
-
然後所有人都需要將 CA 憑證安裝到每個人的電腦中
你可以透過許多方法將 CA 憑證派送到每台電腦中,也可以讓每個人自己下載安裝
每個人的 個人憑證 (Personal Certificate) 都需要透過 CA 憑證進行簽章處理,才能算是一個受信任的憑證
-
你需要準備一張 CRL 憑證,紀錄著所有「被撤銷」的憑證清單,這張憑證一樣要透過 CA 憑證簽署才是合法的、受信任的憑證
你可以先準備好一張空白的 CRL 憑證,並且發佈到一個可公開存取的網站上,取得一個 CRL 網址
-
開始讓員工申請個人用的數位憑證
基本步驟就是先建立 CSR (Certificate Signing Request) 憑證簽署要求檔,然後交由 CA 進行簽署並獲得正式憑證。本篇文章不會特別講解這個過程,我之前已經有許多 OpenSSL 文章分享過這個過程。
建立 CA 憑證
建立 CA 憑證相對簡單,一個命令就可以同時建立「私鑰」與「公鑰」,而「公鑰」其實就是 CA 憑證:
openssl req -new -nodes -sha256 -utf8 -newkey rsa:2048 -keyout ca.key -x509 -days 3650 -out ca.crt
過程中要設定一些憑證屬性:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:TW
State or Province Name (full name) [Some-State]:Taiwan
Locality Name (eg, city) []:Taipei
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Duotify Inc.
Organizational Unit Name (eg, section) []:IT
Common Name (e.g. server FQDN or YOUR name) []:Duotify Global Root CA
Email Address []:
這個命令會產生兩個檔案:
ca.key
(簽署憑證時會需要用到的私密金鑰)
ca.crt
(即 CA 憑證,需派送到每台電腦中)
建立一張空的 CRL 憑證
我們要建立一張 CRL 憑證,主要有以下三個步驟:
-
建立一個空的憑證資料庫檔 (certindex
)
這個檔案將會保存未來透過 CA 憑證簽發個人憑證時的完整記錄,未來要撤銷憑證時,也是去調整這個檔案的內容,你可以把這個檔案當成一個文字格式的資料庫。
我們先建立空白的檔案即可:
touch certindex
-
建立 crlnumber
檔案
每次核發一張新的 CRL 憑證,這個 crlnumber
檔案內容的編號就會遞增(+1
),你可以視為一個 CRL 憑證的序號。
我們可以從 01
開始:
echo 01 > crlnumber
如果你可能會廢止很多憑證的話,這裡的 CRL 可能會很大,此時你很有可能會將 CRL 分段處理,因此 crlnumber
也有可能會從 1000
或 2000
開始計算,基本上這個 CRL Number 可以自由定義其編號起始點。
-
建立 certserial
檔案
其實每張憑證都有個 Serial number
憑證序號,如果你不指定的話,每次核發憑證都會給一段很長的亂碼序號。如果你在建立憑證時有設定 certserial
的話,透過 OpenSSL 建立新的憑證時,就會自動用你的數字來編號,每次簽署新的憑證都會自動以此序號為主,並且會在簽署後自動累加上去 (+1
)。
echo 01 > certserial
-
建立一個 ca.conf
設定檔
[ ca ]
default_ca = myca
[ crl_ext ]
# issuerAltName=issuer:copy #this would copy the issuer name to altname
authorityKeyIdentifier=keyid:always
[ myca ]
dir = ./
new_certs_dir = $dir
unique_subject = no
certificate = $dir/ca.crt
database = $dir/certindex
private_key = $dir/ca.key
serial = $dir/certserial
default_days = 730
default_md = sha1
policy = myca_policy
x509_extensions = myca_extensions
crlnumber = $dir/crlnumber
default_crl_days = 730
[ myca_policy ]
commonName = supplied
stateOrProvinceName = supplied
countryName = optional
emailAddress = optional
organizationName = supplied
organizationalUnitName = optional
[ myca_extensions ]
basicConstraints = CA:false
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always
keyUsage = digitalSignature,keyEncipherment
extendedKeyUsage = serverAuth
crlDistributionPoints = URI:https://blog.miniasp.com/root.crl
-
簽發 DER 格式的 CRL 憑證檔 (root.crl
)
openssl ca -config ca.conf -gencrl -keyfile ca.key -cert ca.crt -out root.crl.pem
openssl crl -inform PEM -in root.crl.pem -outform DER -out root.crl
rm root.crl.pem
-
將檔案上傳到 crlDistributionPoints
指定的網址
建立個人憑證並附上 CRL 網址
-
建立私密金鑰
openssl genrsa -out will.key 4096
-
建立 CSR 憑證簽署要求檔
建立一個 openssl.conf
設定檔,設定憑證的基本資料:
[req]
prompt = no
default_md = sha256
default_bits = 2048
distinguished_name = dn
[dn]
C = TW
ST = Taiwan
L = Taipei
O = Duotify Inc.
OU = IT Department
emailAddress = will.huang@example.com
CN = Will 保哥
產生 CSR 憑證簽署要求檔
openssl req -new -key will.key -out will.csr -config openssl.conf -utf8
-
建立一個簽署憑證時需要的擴充屬性定義檔
假設檔名為 cert_template.conf
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, serverAuth
nsCertType = client, server, email
nsComment = "Duotify Personal Certificate"
crlDistributionPoints = URI:https://blog.miniasp.com/root.crl
-
使用 CA 憑證核發伺服器憑證
openssl ca -config ca.conf -notext -batch -in will.csr -out will.crt -extfile cert_template.conf
核發成功後,會在 certindex
檔案看到以下內容:
V 240831110206Z 01 unknown /CN=Will Huang/ST=Taiwan/C=TW/emailAddress=will.huang@example.com/O=Duotify Inc./OU=IT
-
合併 will.key
與 will.crt
為 PFX (PKCS#12
) 憑證檔 (will.pfx
)
openssl pkcs12 -export -in will.crt -inkey will.key -out will.pfx
撤銷現有憑證
-
指定要撤銷的憑證
openssl ca -config ca.conf -revoke will.crt
撤銷成功後,會在 certindex
檔案看到以下內容:
R 240831110206Z 220901110514Z 01 unknown /CN=Will Huang/ST=Taiwan/C=TW/emailAddress=will.huang@example.com/O=Duotify Inc./OU=IT
-
簽發 DER 格式的 CRL 憑證檔 (root.crl
)
# 先建立 PEM 格式的 `root.crl.pem` 憑證檔
openssl ca -config ca.conf -gencrl -keyfile ca.key -cert ca.crt -out root.crl.pem
# 再將 PEM 格式轉為 DER 格式的憑證檔
openssl crl -inform PEM -in root.crl.pem -outform DER -out root.crl
# 用不到 PEM 格式的檔案就可以砍掉
rm root.crl.pem
-
將檔案上傳到 crlDistributionPoints
指定的網址
驗證憑證是否有效
-
若要驗證憑證是否有效,在 Windows 可能要先設法清除 CRL 快取才行,否則你可能會測試不出效果
certutil -urlcache crl delete
-
如果你可以直接取得 CA 憑證與 CRL 憑證,就可以直接使用 openssl
驗證憑證是否已被撤銷,不需要事先清空快取
# 將 DER 格式轉為 PEM 格式的憑證檔
openssl crl -inform DER -in root.crl -outform PEM -out root.crl.pem
# 合併 CA 憑證與 CRL 憑證
cat ca.crt root.crl.pem > test.pem
# 檢查 will.crt 憑證是否被撤銷
openssl verify -extended_crl -verbose -CAfile test.pem -crl_check will.crt
相關連結