1. 程式人生 > >openssl根證書生成及簽發使用者證書

openssl根證書生成及簽發使用者證書

前段時間研究了一下 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 的解決方案則可以參考這裡

參考文獻

轉載自: http://rhythm-zju.blog.163.com/blog/static/310042008015115718637/