基於 OpenSSL 的 CA 建立及證書籤發

 前段時間研究了一下 SSL/TLS ,看的是 Eric Rescorla 的 SSL and TLS - Designing and Building Secure Systems 的中文版(關於該中文版的惡劣程度,我在之前的一篇 Blog 中已做了嚴厲的批判)。本書的作者沿襲了 Stevens 在其神作 TCP/IP Illustrated 中的思想:使用網絡嗅探進行協議演示。不同的是,作者並沒有使用 tcpdump ,而是使用了自己編寫的專用於嗅探 SSL/TLS 通訊的 ssldump 。爲了對書中的一些內容進行試驗確認,我決定使用 ssldump 進行一些實驗。然而,進行 SSL/TLS 通訊,至少需要一份 CA 簽發的證書纔可以得以完成,僅僅是做個實驗,我自然不會花天價去買個證書,所以決定自己建 CA 簽發證書。

然而,到今天爲止,我也沒有能夠成功地利用 ssldump 嗅探出一個 SSL/TLS 通訊包。爲啥?只因爲用 OpenSSL 建立 CA 簽發證書的過程太麻煩了,以至於我忙活了好久才勉強建了個 CA ,之後又由於其他的事情,耽擱了 ssldump 的實驗,於是就一直沒有下文了。

什麼?有免費的知名 CA 可以提供證書?咳……這個,我也是事後才知道的……不過,利用 OpenSSL 建立 CA 及自行簽發證書的過程倒是很值得一寫。 OpenSSL 的 ca 命令實在是難用,難怪 ca (1) 的 manpage 中這樣寫到:

WARNINGS

The ca command is quirky and at times downright unfriendly.

The ca utility was originally meant as an example of how to do things in a CA. It was not supposed to be used as a full blown CA itself: nevertheless some people are using it for this purpose.

The ca command is effectively a single user command: no locking is done on the various files and attempts to run more than one ca command on the same database can have unpredictable results.

看來,我們這些非要用 OpenSSL 來做 CA 的人本來就是自找麻煩。不過,雖然 OpenSSL 的用戶界面讓人望而卻步,就其功能而言,恐怕是各個相關 FOSS 產品中最爲完備的一款,加之獲取方便,在 Debian 下直接 aptitude install openssl 便可以安裝, Win32 下的話,也可以方便地從在 cygwin 官方鏡像站上獲取。況且,作爲信息安全方面的新手,我對其他相關產品也是一無所知。所以,還是硬着頭皮去啃 OpenSSL 的 man 手冊。利用了兩三天的閒暇時間,在 kghost 的幫助下,我終於掌握了要點。下文便詳細記錄了基於 OpenSSL 的 CA 建立及證書籤發過程。

建立 CA

建立 CA 目錄結構

按照 OpenSSL 的默認配置建立 CA ,需要在文件系統中建立相應的目錄結構。相關的配置內容一般位於 /usr/ssl/openssl.cnf 內,詳情可參見 config (1) 。在終端中使用如下命令建立目錄結構:

$ mkdir -p ./demoCA/{private,newcerts}
$ touch ./demoCA/index.txt
$ echo 01 > ./demoCA/serial

產生的目錄結構如下:

.
`-- demoCA/
    |-- index.txt
    |-- newcerts/
    |-- private/
    `-- serial

生成 CA 證書的 RSA 密鑰對

首先,我們要爲 CA 建立 RSA 密鑰對。打開終端,使用如下命令生成 RSA 密鑰對:

$ openssl genrsa -des3 -out ./demoCA/private/cakey.pem 2048

參數解釋

genrsa

用於生成 RSA 密鑰對的 OpenSSL 命令。

-des3

使用 3-DES 對稱加密算法加密密鑰對,該參數需要用戶在密鑰生成過程中輸入一個口令用於加密。今後使用該密鑰對時,需要輸入相應的口令。如果不加該選項,則不對密鑰進行加密。

-out ./demoCA/private/cakey.pem

令生成的密鑰對保存到文件 ./demoCA/private/cakey.pem

2048

RSA 模數位數,在一定程度上表徵了密鑰強度。

該命令輸出如下,用戶應輸入自己的密鑰口令並確認:

Generating RSA private key, 2048 bit long modulus
................................................+++
.........................+++
e is 65537 (0x10001)
Enter pass phrase for ./demoCA/private/cakey.pem:<enter your pass-phrase>
Verifying - Enter pass phrase for ./demoCA/private/cakey.pem:<re-enter your pass-phrase>

生成 CA 證書請求

爲了獲取一個 CA 根證書,我們需要先製作一份證書請求。先前生成的 CA 密鑰對被用於對證書請求籤名。

$ openssl req -new -days 365 -key ./demoCA/private/cakey.pem -out careq.pem

參數解釋

req

用於生成證書請求的 OpenSSL 命令。

-new

生成一個新的證書請求。該參數將令 OpenSSL 在證書請求生成過程中要求用戶填寫一些相應的字段。

-days 365

從生成之時算起,證書時效爲 365 天。

-key ./demoCA/private/cakey.pem

指定 ./demoCA/private/cakey.pem 爲證書所使用的密鑰對文件。

-out careq.pem

令生成的證書請求保存到文件 careq.pem

該命令將提示用戶輸入密鑰口令並填寫證書相關信息字段,輸出如下:

Enter pass phrase for ./demoCA/private/cakey.pem:<enter you pass-phrase>
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]:CN
State or Province Name (full name) [Some-State]:ZJ
Locality Name (eg, city) []:HZ
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Some Ltd. Corp.
Organizational Unit Name (eg, section) []:Some Unit
Common Name (eg, YOUR name) []:Someone
Email Address []:[email protected]

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

對 CA 證書請求進行簽名

在 實際應用中,用戶可以通過向知名 CA 遞交證書請求來申請證書。但是在這裏,我們需要建立的是一個根 CA ,只能由我們自己來對證書請求進行簽名。所以我們讓 OpenSSL 使用證書請求中附帶的密鑰對對該請求進行簽名,也就是所謂的“ self sign ”:

$ openssl ca -selfsign -in careq.pem -out cacert.pem

參數解釋

ca

用於執行 CA 相關操作的 OpenSSL 命令。

-selfsign

使用對證書請求進行簽名的密鑰對來簽發證書。

-in careq.pem

指定 careq.pem 爲證書請求文件。

-out ./demoCA/cacert.pem

指定 ./demoCA/cacert.pem 爲輸出的證書。

該命令要求用戶輸入密鑰口令並輸出相關證書信息,請求用戶確認:

Using configuration from /usr/lib/ssl/openssl.cnf
Enter pass phrase for ./demoCA/private/cakey.pem:<enter your pass-phrase>
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number: 2 (0x2)
        Validity
            Not Before: Jan 16 13:05:09 2008 GMT
            Not After : Jan 15 13:05:09 2009 GMT
        Subject:
            countryName = CN
            stateOrProvinceName = ZJ
            organizationName = Some Ltd. Corp.
            organizationalUnitName = Some Unit
            commonName = Someone
            emailAddress = [email protected]
        X509v3 extensions:
            X509v3 Basic Constraints:
                CA:FALSE
            Netscape Comment:
                OpenSSL Generated Certificate
            X509v3 Subject Key Identifier:
                75:F5:3C:CC:C1:5E:6D:C3:8B:46:A8:08:E6:EA:29:E8:22:7E:70:03
            X509v3 Authority Key Identifier:
                keyid:75:F5:3C:CC:C1:5E:6D:C3:8B:46:A8:08:E6:EA:29:E8:22:7E:70:03

Certificate is to be certified until Jan 15 13:05:09 2009 GMT (365 days)
Sign the certificate? [y/n]:y


1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

一步完成 CA 證書請求生成及簽名

以上兩個步驟可以合二爲一。利用 ca 命令的 -x509 參數,通過以下命令同時完成證書請求生成和簽名從而生成 CA 根證書:

$ openssl req -new -x509 -days 365 -key ./demoCA/private/cakey.pem -out ./demoCA/cacert.pem

參數解釋

req

用於生成證書請求的 OpenSSL 命令。

-new

生成一個新的證書請求。該參數將令 OpenSSL 在證書請求生成過程中要求用戶填寫一些相應的字段。

-x509

生成一份 X.509 證書。

-days 365

從生成之時算起,證書時效爲 365 天。

-key ./demoCA/private/cakey.pem

指定 cakey.pem 爲證書所使用的密鑰對文件。

-out ./demoCA/cacert.pem

令生成的證書保存到文件 ./demoCA/cacert.pem

該命令輸出如下,用戶應輸入相應的字段:

Enter pass phrase for ./demoCA/private/cakey.pem:
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]:CN
State or Province Name (full name) [Some-State]:ZJ
Locality Name (eg, city) []:HZ
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Some Ltd. Corp.
Organizational Unit Name (eg, section) []:Some Unit
Common Name (eg, YOUR name) []:Someone
Email Address []:[email protected]

至此,我們便已成功建立了一個私有根 CA 。在這個過程中,我們獲得了一份 CA 密鑰對文件 ./demoCA/private/cakey.pem 以及一份由此密鑰對簽名的 CA 根證書文件 ./demoCA/cacert.pem ,得到的 CA 目錄結構如下:

.
|-- careq.pem
`-- demoCA/
    |-- cacert.pem
    |-- index.txt

    |-- index.txt.attr
    |-- index.txt.old
    |-- newcerts/
    |   `-- 01.pem
    |-- private/
    |   `-- cakey.pem
    |-- serial
    `-- serial.old

注:如果在 CA 建立過程中跳過證書請求生成的步驟,則不會產生 careq.pem 文件。

簽發證書

下面我們就可以利用建立起來的 CA 進行證書籤發了。

生成用戶證書 RSA 密鑰對

參照 CA 的 RSA 密鑰對生成過程,使用如下命令生成新的密鑰對:

$ openssl genrsa -des3 -out userkey.pem
Generating RSA private key, 512 bit long modulus
....++++++++++++
...++++++++++++
e is 65537 (0x10001)
Enter pass phrase for userkey.pem:<enter your pass-phrase>
Verifying - Enter pass phrase for userkey.pem:<re-enter your pass-phrase>

生成用戶證書請求

參照 CA 的證書請求生成過程,使用如下命令生成新的證書請求:

$ openssl req -new -days 365 -key userkey.pem -out userreq.pem
Enter pass phrase for userkey.pem:<enter your pass-phrase>
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]:CN
State or Province Name (full name) [Some-State]:ZJ
Locality Name (eg, city) []:HZ
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Some Ltd. Corp.
Organizational Unit Name (eg, section) []:Some Other Unit
Common Name (eg, YOUR name) []:Another
Email Address []:[email protected]

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

簽發用戶證書

現在,我們可以用先前建立的 CA 來對用戶的證書請求進行簽名來爲用戶簽發證書了。使用如下命令:

$ openssl ca -in userreq.pem -out usercert.pem

參數解釋

ca

用於執行 CA 相關操作的 OpenSSL 命令。

-in userreq.pem

指定用戶證書請求文件爲 userreq.pem

-out usercert.pem

指定輸出的用戶證書文件爲 usercert.pem

該命令要求用戶輸入密鑰口令並輸出相關證書信息,請求用戶確認:

Using configuration from /usr/lib/ssl/openssl.cnf
Enter pass phrase for ./demoCA/private/cakey.pem:<enter your pass-phrase>
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number: 2 (0x2)
        Validity
            Not Before: Jan 16 14:50:22 2008 GMT
            Not After : Jan 15 14:50:22 2009 GMT
        Subject:
            countryName               = CN
            stateOrProvinceName       = ZJ
            organizationName          = Some Ltd. Corp.
            organizationalUnitName    = Some Other Unit
            commonName                = Another
            emailAddress              = [email protected]
        X509v3 extensions:
            X509v3 Basic Constraints:
                CA:FALSE
            Netscape Comment:
                OpenSSL Generated Certificate
            X509v3 Subject Key Identifier:
                97:E7:8E:84:B1:45:27:83:94:A0:DC:24:79:7B:83:97:99:0B:36:A9
            X509v3 Authority Key Identifier:
                keyid:D9:87:12:94:B2:20:C7:22:AB:D4:D5:DF:33:DB:84:F3:B0:4A:EC:A2

Certificate is to be certified until Jan 15 14:50:22 2009 GMT (365 days)
Sign the certificate? [y/n]:y


1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

至此,我們便完成了 CA 的建立及用戶證書籤發的全部工作。不妨把所有 shell 命令放到一起縱覽一下:

# 建立 CA 目錄結構
mkdir -p ./demoCA/{private,newcerts}
touch ./demoCA/index.txt
echo 01 > ./demoCA/serial

# 生成 CA 的 RSA 密鑰對
openssl genrsa -des3 -out ./demoCA/private/cakey.pem 2048

# 生成 CA 證書請求
openssl req -new -days 365 -key ./demoCA/private/cakey.pem -out careq.pem

# 自簽發 CA 證書
openssl ca -selfsign -in careq.pem -out ./demoCA/cacert.pem

# 以上兩步可以合二爲一
openssl req -new -x509 -days 365 -key ./demoCA/private/cakey.pem -out ./demoCA/cacert.pem

# 生成用戶的 RSA 密鑰對
openssl genrsa -des3 -out userkey.pem

# 生成用戶證書請求
openssl req -new -days 365 -key userkey.pem -out userreq.pem

# 使用 CA 簽發用戶證書
openssl ca -in userreq.pem -out usercert.pem

瞭解了這些基礎步驟之後,就可以通過腳本甚至 makefile 的方式來將這些工作自動化。 CA.plCA.sh 便是對 OpenSSL 的 CA 相關功能的簡單封裝,在 Debian 系統中,安裝了 OpenSSL 後,可以在 /usr/lib/ssl/misc/ 目錄下找到這兩個文件。而 makefile 的解決方案則可以參考這裏

參考文獻

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