密碼學系列之:PKI的證書格式表示X.509

2022-06-22 21:01:15

簡介

在PKI(public key infrastructure)公鑰設施基礎體系中,所有的一切操作都是圍繞著證書和金鑰的,它提供了建立、管理、分發、使用、儲存和復原數位憑證以及管理公鑰加密所需的一組角色、策略、硬體、軟體和程式。

有了金鑰,就可以根據金鑰製作證書了。要想證書可以被廣泛的使用,一個通用的標準肯定是少不了的,在PKI體系中,這個證書的標準就叫做X.509。

X.509 標準定義了公鑰證書最常用的格式。

一個證書的例子

證書中最主要就是公鑰資訊,從證書中提取公鑰,才能使用公鑰去解密傳送者使用私鑰加密過的資料。公鑰資訊是證書的核心。

除了公鑰之外,證書包含了很多其他的資訊,比如包含了身份資訊(主機名、組織或個人等)。

建立證書非常簡單,我們先看一個使用openssl命令來建立證書的例子。

建立證書之前,首先需要建立證書依賴的公鑰和私鑰,x.509證書可以支援多種公鑰私鑰演演算法,比如RSA, DSA, ECDSA, ed25519等。

這裡我們選擇使用RSA演演算法,生成金鑰對如下:

openssl genrsa -des3 -out ca.key 1024
Generating RSA private key, 1024 bit long modulus
...............++++++
.............................................++++++
e is 65537 (0x10001)
Enter pass phrase for ca.key:
Verifying - Enter pass phrase for ca.key:

輸入pass, 我們可以得到ca.key,這是一個RSA PRIVATE KEY。

接下來就可以用這個ca.key來建立證書。

openssl req -new -x509 -days 20 -key ca.key -out ca.crt
Enter pass phrase for ca.key:
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) []:SH
State or Province Name (full name) []:SH
Locality Name (eg, city) []:SH
Organization Name (eg, company) []:HW
Organizational Unit Name (eg, section) []:HW
Common Name (eg, fully qualified host name) []:caserver
Email Address []:[email protected]

可以看到,在金鑰的基礎上,證書還需要提供例如Country Name,Province Name,Organization Name等額外資訊。

最後,我們可以得到一個CA證書ca.crt。

如果想要檢視證書的狀態,可以使用下面的命令:

openssl x509 -noout -text -in ca.crt
Certificate:
    Data:
        Version: 1 (0x0)
        Serial Number: 9511149647544559472 (0x83fe64365379a770)
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=SH, ST=SH, L=SH, O=HW, OU=HW, CN=caserver/[email protected]
        Validity
            Not Before: Apr 27 06:33:16 2022 GMT
            Not After : May 17 06:33:16 2022 GMT
        Subject: C=SH, ST=SH, L=SH, O=HW, OU=HW, CN=caserver/[email protected]
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (1024 bit)
                Modulus:
                    00:9f:b4:ff:16:15:51:2a:de:2f:23:cd:7d:27:41:
                    3c:30:1f:f3:cb:bf:3f:7c:96:ba:c3:81:a8:eb:88:
                    be:11:31:03:6f:c3:1d:f1:dc:4c:ea:3d:da:15:24:
                    59:32:8b:7e:87:a0:0b:57:b9:79:e4:72:2f:4b:50:
                    9d:00:eb:ee:52:24:f3:e8:e9:92:1c:ec:47:d9:98:
                    8c:f9:0f:71:a6:91:b2:5b:c1:59:bf:1f:27:47:6b:
                    9c:ce:22:e7:9d:2c:4a:3a:83:72:43:47:5d:ee:9e:
                    64:78:cb:3c:48:af:27:08:c1:08:41:c0:e0:92:e9:
                    13:81:1c:c7:72:3c:2f:5f:f3
                Exponent: 65537 (0x10001)
    Signature Algorithm: sha256WithRSAEncryption
         68:09:be:cb:89:c0:0d:27:d2:bb:b2:f0:fb:6e:e2:0a:19:86:
         92:cf:e5:90:48:b7:99:02:f1:75:6a:6d:79:1e:18:c7:95:7c:
         89:92:ed:a1:bf:ad:91:76:c6:63:59:bb:6d:31:1e:11:5a:5e:
         32:86:12:89:00:69:d0:77:c6:d6:69:11:0a:f7:7b:61:6e:95:
         f8:d6:6b:89:c0:6c:49:eb:38:d9:f5:82:43:32:6e:14:fb:a0:
         fb:be:12:a5:dc:69:66:b8:1b:22:cb:0f:9f:56:52:40:6d:48:
         b6:78:29:dc:67:aa:79:c5:00:e3:68:9a:65:9a:94:99:be:ce:
         b0:d2

可以看到CA證書中包含了日期,序列號,簽名演演算法,發行者,有效性等額外的資訊。

上面生成的證書實際上是一個根證書,這個根證書可以對其他的證書請求進行簽名,從而生成子證書,從而產生了證書的級聯結構。

如果一個使用者端想要向CA server請求一個新的證書該怎麼做呢?

首先使用者端也需要生成自己的金鑰對。如果使用者端是CA server自己,那麼這個請求CA證書的過程叫做自簽名。

要想請求證書,首先得生成一個請求csr,同樣可以使用openssl命令來進行:

openssl req -new -key ca.key -out server.csr
Enter pass phrase for ca.key:
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) []:CN
State or Province Name (full name) []:SH
Locality Name (eg, city) []:SH
Organization Name (eg, company) []:citi
Organizational Unit Name (eg, section) []:org
Common Name (eg, fully qualified host name) []:client
Email Address []:[email protected]

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:

csr請求因為也是需要生成一個CA證書,所以也需要輸入類似的資訊。

最後我們生成了一個server.csr檔案。

接下來使用這個csr檔案去請求證書:

openssl x509 -req -days 20 -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt
Signature ok
subject=/C=CN/ST=SH/L=SH/O=citi/OU=org/CN=client/[email protected]
Getting CA Private Key
Enter pass phrase for ca.key:

上面命令的含義是CA server上的private key,根證書和剛剛生成的證書請求server.csr,生成使用CA server簽名的自簽名證書。

最後得到一個自簽名server.csr證書檔案。

同樣使用openssl命令檢視該證書狀態:

openssl x509 -noout -text -in server.crt

Certificate:
    Data:
        Version: 1 (0x0)
        Serial Number: 14663444799761243679 (0xcb7f055ae9515e1f)
    Signature Algorithm: sha1WithRSAEncryption
        Issuer: C=SH, ST=SH, L=SH, O=HW, OU=HW, CN=caserver/[email protected]
        Validity
            Not Before: Apr 27 07:28:08 2022 GMT
            Not After : May 17 07:28:08 2022 GMT
        Subject: C=CN, ST=SH, L=SH, O=citi, OU=org, CN=client/[email protected]
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (1024 bit)
                Modulus:
                    00:9f:b4:ff:16:15:51:2a:de:2f:23:cd:7d:27:41:
                    3c:30:1f:f3:cb:bf:3f:7c:96:ba:c3:81:a8:eb:88:
                    be:11:31:03:6f:c3:1d:f1:dc:4c:ea:3d:da:15:24:
                    59:32:8b:7e:87:a0:0b:57:b9:79:e4:72:2f:4b:50:
                    9d:00:eb:ee:52:24:f3:e8:e9:92:1c:ec:47:d9:98:
                    8c:f9:0f:71:a6:91:b2:5b:c1:59:bf:1f:27:47:6b:
                    9c:ce:22:e7:9d:2c:4a:3a:83:72:43:47:5d:ee:9e:
                    64:78:cb:3c:48:af:27:08:c1:08:41:c0:e0:92:e9:
                    13:81:1c:c7:72:3c:2f:5f:f3
                Exponent: 65537 (0x10001)
    Signature Algorithm: sha1WithRSAEncryption
         31:2e:b6:d7:3e:2d:ae:f1:2e:44:b5:5e:73:42:91:39:80:9f:
         a8:ed:9c:60:78:35:21:df:4a:45:b0:b1:d1:80:c1:ee:cb:30:
         75:34:66:61:43:6c:0a:85:4f:a3:e5:09:9f:2b:07:62:6a:3a:
         60:22:78:f0:7d:32:ef:2f:46:95:34:60:22:03:47:78:6f:0c:
         7e:f1:85:ea:d6:4b:1e:45:b5:56:a1:d7:52:9c:19:ae:24:26:
         3d:a7:0b:f2:94:c1:d3:e3:04:25:f8:ce:b8:cb:84:6a:d1:b4:
         63:7c:df:87:f8:44:86:49:b5:96:dc:43:c7:7a:17:d3:82:c6:
         6a:af

可以看到結構和root ca證書是一樣的,這裡的Subject是建立server.csr中輸入的資訊。

X.509證書的字尾

上面我們使用的證書字尾是crt,也就是certificate的縮寫。

事實上X.509證書還支援其他幾種型別的字尾。

.pem

pem的全稱是Privacy-enhanced Electronic Mail,從名字可以看出,pem最初是為加密郵件準備的。

它是一種以DER+Base64進行編碼的證書。PEM證書通常是文字格式,以"-----BEGIN CERTIFICATE-----"開頭,並以"-----END CERTIFICATE-----"結束。

.cer, .crt, .der

這三個都是以DER進行編碼的二進位制證書,但有時候也會使用Base64進行編碼,比如.pem。

.p7b, .p7c

是用 PKCS#7 進行簽名的資料。

PKCS 全稱是 Public-Key Cryptography Standards ,是由RSA實驗室與其它安全系統開發商為促進公鑰密碼的發展而制訂的一系列標準。

PKCS#7的全稱叫做Cryptographic Message Syntax Standard。

.p12

是用PKCS#12簽名的資料,可以同時包含證書和私鑰。

.pfx

PKCS#12 的前身,通常包含 PKCS#12 格式的資料。

證書的層級結構和交叉認證

證書的層級結構應該很好理解了,證書的層級結構又叫做證書鏈。

從我們收到的最終證書開始,後面可以跟一個或者多個CA證書,最後一個證書是根證書。

比如現在證書的鏈式結構是A->B->C。

要想校驗A證書的有效性,那麼需要使用到B的公鑰來驗證,那麼B的有效性,同樣需要用到C的公鑰來驗證,這樣層級驗證一直到根證書為止。

什麼是交叉認證呢?

假如現在有A->B和D->E這兩條證書鏈。但是現在這兩條鏈是獨立的,假如A證書也想使用E來進行認證應該怎麼處理呢?

先來考慮下A->B的含義,A->B意思是A證書使用B證書來簽名的。更確切的說就是A證書是用B證書中的公鑰來進行簽名的。

如果我們使用E對B中的公鑰進行簽名得到一個證書C,那麼B和C擁有相同的公鑰,所以對於A來說,A->B和 A->C->E 都是有效的證書鏈。

如果使用B對E的公鑰進行簽名,得到證書F,那麼對於D->E和 D->F->B 同樣是兩條有效的證書鏈。

這樣的結構就叫做交叉認證。

交叉認證用在不同根CA鏈互相認證的場景,非常有用。

x.509證書的使用範圍

x.509證書使用範圍非常廣泛,比如web存取中最常見的TLS/SSL 和 HTTPS 都是用的是x.509證書。

另外SMTP, POP, IMAP, LDAP, XMPP提供了對x.509證書的支援。

總結

以上就是x.509證書的使用和相關原理的介紹。

更多內容請參考 http://www.flydean.com/42-pki-x509/

最通俗的解讀,最深刻的乾貨,最簡潔的教學,眾多你不知道的小技巧等你來發現!

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