如何使用OpenSSL工具生成根證書與應用證書
一、步驟簡記
- // 生成頂級CA的公鑰證書和私鑰文件,有效期10年(RSA 1024bits,默認)
- openssl req -new -x509 -days 3650 -keyout CARoot1024.key -out CARoot1024.crt
- // 為頂級CA的私鑰文件去除保護口令
- openssl rsa -in CARoot1024.key -out CARoot1024.key
- // 生成頂級CA的公鑰證書和私鑰文件,有效期15年(RSA 2048bits,指定)
- openssl req -newkey rsa:2048 -x509 -days 5480 -keyout CARoot2048.key -out CARoot2048.crt
- // 為頂級CA的私鑰文件去除保護口令
- openssl rsa -in CARoot2048.key -out CARoot2048.key
- // 為應用證書/中級證書生成私鑰文件
- openssl genrsa -out app.key 2048
- // 根據私鑰文件,為應用證書/中級證書生成 csr 文件(證書請求文件)
- openssl req -new -key app.key -out app.csr
- // 使用CA的公私鑰文件給 csr 文件簽名,生成應用證書,有效期5年
- openssl ca -in app.csr -out app.crt -cert CARoot1024.crt -keyfile CARoot1024.key -days 1826 -policy policy_anything
- // 使用CA的公私鑰文件給 csr 文件簽名,生成中級證書,有效期5年
- openssl ca -extensions v3_ca -in app.csr -out app.crt -cert CARoot1024.crt -keyfile CARoot1024.key -days 1826 -policy policy_anything
以上是生成根證書與應用證書過程中要用到的所有命令,根據生成目標不同,分為三組。其中,前面兩組都用於生成自簽名的頂級CA(區別只在於密鑰長度不同),實際應用中只需根據需求選擇一組即可。
最后一組用於生成非自簽名的證書,包括中級證書與應用證書。所謂中級證書,是具有繼續頒發下級證書權限的子CA,而本文中所說的應用證書,特指不能用來繼續頒發下級證書,只能用來證明個體身份的證書。頂級CA在簽發二者的時候,只是多少一個 -extensions v3_ca 選項的區別,這個選項賦予被簽發的證書繼續簽發下級證書的權力。
二、各步詳解
2.1 生成自簽名根證書(即頂級CA)
典型示例:openssl req -new-x509 -days5480 -keyoutCA.key -outCA.crt
[1] 命令選項和參數解讀
示例中,各選項(及參數)的意義如下:
- req 使用openssl的req子命令
- -new 生成新的證書請求
- -x509 生成自簽名證書
- -days 5480 自簽名證書的有效期5480天(15年)【僅當使用了 -x509 選項后有效】
- -keyout CA.key 私鑰文件名指定為CA.key【若為運行前就已有的私鑰文件且原名不是CA.key,則改名為CA.key;否則新生成的私鑰文件命名為CA.key】
- -out CA.crt 指定輸出所生成自簽名證書的信息到文件,且文件名為CA.crt【建議不要省略】
其中,-days,-keyout 兩個選項可以省略,省略的話使用默認值,有效期默認為 30 天【由程序內部在變量初始化的時候指定,與配置文件無關】,私鑰文件名的默認值由配置文件 openssl.cnf 中相關條目指定,沒改過的話為 privkey.pem。
選項 -out 若是省略的話,openssl不會以文件形式輸出生成的 證書/證書請求,而是會默認將文件的信息直接打印到屏幕上,這在大多數情況下,是不符合我們要求的。所以建議這個選項最好不要省略!
req子命令可以通過 -key 選項為證書請求指定使用一個已存在的私鑰文件。但在示例中的情況下,雖然使用了-new 和 -x509兩個選項,但沒有使用 -key 選項,這時,req子命令會自動為自簽名證書生成一個RSA私鑰,密鑰長度的默認值由配置文件 openssl.cnf 中的相關條目指定,沒改過的話為 1024 bits。
[2] 關於私鑰文件加密口令的指定
運行中會提示輸入加密口令,如下:
- writing new private key to 'CA.key'
- Enter PEM pass phrase:
- Verifying - Enter PEM pass phrase:
此口令用於加密私鑰文件 CA.key 中的私鑰信息,如果不想在運行過程中還要輸入加密口令,則可以使用選項 -passout 在命令中直接指定。選項 -passout 的使用形式為:
-passoutarg
其中,arg是選項 -passout 的參數,其格式有多種,詳參《OpenSSL官方文檔》中關於"PASS_PHRASE_ARGUMENTS"的介紹。
本小節典型示例中的命令,可以用選項 -passout 改造如下:
openssl req -new-x509 -days5480 -keyoutCA.key -out CA.crt-passoutpass:1314
由於Linux系統中可以使用history命令查看歷史指令記錄,所以出於安全方面的考量,一般如非必要,不建議在命令中直接指定口令。這與MySQL登錄的時候不在 -p 選項里直接指定登錄口令的原因是一致的。
[3] 關於證書請求文件中的DN字段
運行中會提示輸入一些 Distinguished Name fields,即證書的識別名信息字段,簡稱為DN字段,如下:
- 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) [GB]:US
- State or Province Name (full name) [Berkshire]:California
- Locality Name (eg, city) [Newbury]:
- Organization Name (eg, company) [My Company Ltd]:GeoAuth Inc.
- Organizational Unit Name (eg, section) []:.
- Common Name (eg, your name or your server's hostname) []:Authentication Global Root
- Email Address []:.
這些DN字段大部分有默認值,默認值由配置文件 openssl.cnf中相關條目指定。如要在某一個DN字段使用默認值,則無需輸入任何信息,直接點擊"Enter"鍵;如果確實某個DN字段的值要置為空,則輸入一個 '.' 后,點擊"Enter"鍵。
這些DN字段主要是拿來識別證書持有者身份的,下表是關於它們的縮寫、說明和一些填寫說明。【此部分參考了互動百科的SSL條目】
| DN字段名 | 縮寫 | 說明 | 填寫要求 |
| Country Name | C | 證書持有者所在國家 | 要求填寫國家代碼,用2個字母表示 |
| State or Province Name | ST | 證書持有者所在州或省份 | 填寫全稱,可省略不填 |
| Locality Name | L | 證書持有者所在城市 | 可省略不填 |
| Organization Name | O | 證書持有者所屬組織或公司 | 最好還是填一下 |
| Organizational Unit Name | OU | 證書持有者所屬部門 | 可省略不填 |
| Common Name | CN | 證書持有者的通用名 | 必填。 對於非應用證書,它應該在一定程度上具有惟一性; 對於應用證書,一般填寫服務器域名或通配符樣式的域名。 |
| Email Address | 證書持有者的通信郵箱 | 可省略不填 |
表2-1 DN字段的說明
注:表中所謂,證書不是應用證書時,其持有者的通用名要有“唯一性”,是指其通用名不要與一般主機上常見的信任證書列表或撤銷證書列表中的證書產生重復。
如果不想在運行過程中逐個輸入這些DN字段的值,則可以使用 -subj 選項在命令中直接指定。選項 -subj 的使用形式為:
-subj arg
其中,arg是選項 -subj 的參數,其格式類似於:/type0=value0/type1=value1/type2=... 形式。每一個 /type=value 形式的單元,都對應了一個完整的DN字段。其中,
/ 是每一個DN字段的開始標志;type0、type1等等,就是表2-1中提到的DN字段名的縮寫;=是DN字段的名和值之間的間隔符;
value0、value1等等,就是原本你要在運行過程中逐個輸入的DN字段的值。
對於您要將值置為空的DN字段,您可以略去不寫。本小節典型示例中的命令,可以用 -subj 選項改造如下【略去了 L 與 OU 兩個DN字段】:
openssl req -new-x509 -days5480 -subj/C=US/ST=California/O=GeoAuth\ Inc./CN=Authentication\ Global\ Root -keyout CA.key -out CA.crt
需要特別注意的是,如果您設定的DN字段的值如果存在一些特殊字符【比如 (空格)、((半角左括號)、)(半角右括號)……】,必須經過\(反斜桿)轉義。上例中已經給出了空格轉義的情況。
[4] 如何指定自簽名證書的密鑰長度和類型
如前所述,示例只能生成密鑰長度為1024bits的RSA公私鑰對。如果要生成密鑰長度不為1024bits的RSA公私鑰對,或是其他類型的【比如DSA、EC】公私鑰對,則必須使用選項 -newkey 來代替 -new 。選項 -newkey 的用法比較復雜,如需詳細了解,請參看《OpenSSL官方文檔》的相關頁面。本小節典型示例中的命令等效於以下命令:
openssl req -newkeyrsa:1024 -x509 -days5480-keyoutCA.key -outCA.crt
要生成一個密鑰長度為2048bits的RSA公私鑰對,命令為:
openssl req -newkeyrsa:2048 -x509 -days5480-keyoutCA2048.key -outCA2048.crt
2.2 為頂級CA的私鑰文件去除加密保護
上節提到,頂級CA的私鑰文件是經過加密保護的,以后每當需讀取 CA.key 文件中的私鑰信息時,都需輸入解密口令。這種做法適合有安全需求的場合,但如果覺得不方便,也可以去除這個口令。
典型示例:openssl rsa -inCA.key -outCA.key
[1] 命令選項和參數解讀
示例中,各選項/參數的意義如下:
- rsa 使用openssl的rsa子命令
- -in CA.key 經加密保護的私鑰文件
- -out CA.key 解除加密保護后的私鑰文件【可以改名】
[2] 關於私鑰文件解密口令的指定
運行中會提示輸入解密口令,如下:,
- Enter pass phrase for CA.key:
- writing RSA key
如果不想在運行過程中還要輸入解密口令,則可以使用選項 -passin 在命令中直接指定。選項 -passin 的使用形式為:
-passinarg
其中,arg是選項 -passin 的參數,其格式同選項 -passout 的參數,詳參《OpenSSL官方文檔》中關於"PASS_PHRASE_ARGUMENTS"的介紹。
本小節典型示例中的命令,可以用選項 -passin 改造如下:
openssl rsa -inCA.key -out CA.key -passin pass:1314
基於同選項 -passout 一樣的考量,一般不建議直接在命令中指定解密口令。
[3] rsa子命令的實際功能
rsa子命令的功能,更完整來說,應該是RSA密鑰的管理。除了此處用到的去除加密保護,還可以用來:更換加解密口令,更換加解密算法【DES、三重DES、IDEA(官方文檔上提到過,但是有些版本好像不支持,比如說我安裝的)、AES(官方文檔上沒提到,我安裝的版本支持)】,更換密鑰文件的編碼方式,等等。
2.3 為應用證書/中級證書生成私鑰文件
典型示例:openssl genrsa-outapp.key 2048
[1] 命令選項和參數解讀
示例中,各選項/參數的意義如下:
- genrsa 使用openssl的genrsa子命令
- -out app.key 指定輸出生成的私鑰信息到文件,且文件名為app.key【建議別省略】
- 2048 指定所生成私鑰的比特長度【務必放在最后一個】
其中,選項 -out 若是省略的話,openssl不會以文件形式輸出生成的 私鑰信息,而是會默認將私鑰的信息直接打印到屏幕上,這不符合我們的要求。所以建議這個選項不要省略!
genrsa子命令還可以有其他一些選項及參數,但不論還有多少選項,都必須把指定私鑰長度的參數放在最后一個。【如果指定私鑰長度的參數不是最后一個,則其后的參數好像會被舍棄。】
[2] 私鑰文件的加密保護
本小節典型示例所給出的命令,生成的是未經任何加密保護的私鑰文件。這種方式用起來比較方便,但非常不安全。如果要為私鑰文件附加加密保護,則有兩種方式:
A.在生成私鑰文件的同時就指定輸出前要用某種加密算法加密保護;
B.生成明文的私鑰文件后用 rsa 子命令附加某種加密算法的加密保護。
我計算機上安裝的openssl版本,在兩種方式下都支持這些加密算法選項:-des,-des3,-aes128,-aes192,-aes256。以加密選用192位的AES算法為例,命令如下:
- // 在生成私鑰文件的同時就指定輸出前要用192位的AES算法加密保護
- openssl genrsa -aes192 -out app.key 1024
- // 生成明文的私鑰文件后用 rsa 子命令附加192位的AES算法加密保護
- openssl rsa -aes192 -in app.key -out app.key
上例中的兩個命令,都會要求在運行中輸入加密口令。同樣的,雖然不建議,但是openssl依然支持在命令中使用選項 -passout 指定加密口令,選項 -passout 的用法參考2.1小節。唯一需要額外注意的是,對於genrsa子命令,選項 -passout 應放在 指定密鑰長度的參數 前面。
2.4 為應用證書/中級證書生成 csr 文件【證書請求文件】
典型示例:openssl req -keyapp.key -out app.csr
[1] 命令選項和參數解讀
示例中,各選項/參數的意義如下:
- req 使用openssl的req子命令
- -new 生成新的證書請求
- -key app.key 指定是為app.key文件中的私鑰生成證書請求
- -out app.csr 指定輸出所生成證書請求的信息到文件,且文件名為app.csr
這和2.1節使用的是openssl的同一個子命令,所以參數的意義很多具有共通性。命令運行中也會要求輸入一些DN字段的值,參看本文2.1 [3] 中的相關介紹。同樣的,可以使用-subj選項在命令中直接指定這些DN字段的值。
2.5 為 csr 文件簽名,生成應用證書/中級證書
典型示例:openssl ca-inapp.csr -outapp.crt -certCA.crt -keyfileCA.key -days1826 -policypolicy_anything
[1] 命令選項和參數解讀
示例中,各選項/參數的意義如下:
- ca 使用openssl的ca子命令
- -in app.csr 指定待簽發證書的 CSR文件為 app.csr
- -out app.crt 指定輸出所簽發證書的信息到文件,且文件名為app.crt【建議不要省略】
- -cert CA.crt 指定為應用/中級證書簽名的CA的公鑰證書為CA.crt【用到CA證書的持有者信息】
- -keyfile CA.key 指定為應用/中級證書簽名的CA的私鑰文件為CA.key【用CA私鑰實際執行簽名】
- -days 1826 指定所簽發證書的有效期為1826天(5年)
- -policy policy_anything 指定簽發策略為 policy_anything 【即,允許所簽發證書的持有者信息和頒發者信息之間不遵守任何匹配策略】
其中,選項 -out 若是省略的話,openssl不會以文件形式輸出生成的 應用證書/中級證書信息,而是會默認將證書的信息直接打印到屏幕上,這一般不符合我們的要求。所以建議這個選項不要省略!
[2] 關於簽發策略
留待下次補充。先參看這這篇吧,http://hi.baidu.com/mars208/item/3b3022ec95a9d704570f1d49
[3] 關於簽發中級證書(二級/三級CA,子CA)
留待下次補充。先參看這這篇吧,http://blog.chinaunix.NET/uid-311680-id-2973653.html
