使用keytool模擬CA證書(shū)頒發(fā)過(guò)程

本章是HTTPS那些事兒的第四篇文章,其他相關(guān)文章請(qǐng)參見(jiàn):前言
本篇主要介紹怎么使用jdk中的keytool工具模擬HTTPS證書(shū)頒發(fā),通過(guò)該工具我們可以模擬CA證書(shū)的申請(qǐng)過(guò)程,CA證書(shū)的申請(qǐng)步驟可以參見(jiàn)本系列的第一篇文章HTTPS基礎(chǔ)。

* 注意

本文純手工打造,轉(zhuǎn)載請(qǐng)注明出處。

首先,要模擬CA證書(shū)的頒發(fā)過(guò)程以及驗(yàn)證CA證書(shū)的有效性,需要定義三個(gè)主體對(duì)象:CA機(jī)構(gòu),服務(wù)器SERVER和客戶端Client,后續(xù)我們將依次描述三個(gè)主體在該過(guò)程中所需要做的工作。

1. 模擬CA機(jī)構(gòu)

作為一個(gè)CA機(jī)構(gòu),我們需要有自己的公私鑰:ca.pub和ca.pri。有了公鑰后,CA需要將公鑰封裝成證書(shū)(包含公鑰和CA本身信息)并發(fā)布出去,所有信任該CA機(jī)構(gòu)的客戶端會(huì)將該證書(shū)安裝到其信任證書(shū)列表中。
下面,我們通過(guò)A、B兩步來(lái)生成CA機(jī)構(gòu)的證書(shū)。

A). 生成CA公私鑰文件

如果使用keytool生成證書(shū),只會(huì)先生成一個(gè)同時(shí)包含公私鑰以及CA本身信息的文件:MyCA.jks,但生成后可以導(dǎo)出CA機(jī)構(gòu)的證書(shū):MyCA.crt。此處的MyCA代表我們模擬的CA機(jī)構(gòu)的名字。

keytool -genkeypair -keyalg RSA -keysize 2048 -keystore MyCA.jks -alias MyCA

該命令指定生成一個(gè)公私鑰對(duì),使用RAS算法,key長(zhǎng)度為2048,生成到文件MyCA.jks中,文件中保存的公私鑰對(duì)的名稱(chēng)為MyCA。使用該命令后會(huì)提示輸入MyCA本身信息,如下:

Enter keystore password:  
Re-enter new password: 
What is your first and last name?
  [Unknown]:  myca
What is the name of your organizational unit?
  [Unknown]:  mallen's ca          
What is the name of your organization?
  [Unknown]:  mallen
What is the name of your City or Locality?
  [Unknown]:  chengdu
What is the name of your State or Province?
  [Unknown]:  sichuan
What is the two-letter country code for this unit?
  [Unknown]:  CN
Is CN=myca, OU=mallen's ca, O=mallen, L=chengdu, ST=sichuan, C=CN correct?
  [no]:  y
Enter key password for <MyCA>
    (RETURN if same as keystore password):

首先要求輸入keystore文件,也就是MyCA.jks文件的訪問(wèn)密碼。然后,輸入first and last name。再之后輸入單位、部門(mén)、城市、省份、國(guó)家編碼,然后要求確認(rèn)是否正確,最后再輸入MyCA私鑰的加密密鑰,直接回車(chē),使用keystore文件密鑰即可。
密鑰對(duì)文件生成后,可以通過(guò)如下命令查看文件內(nèi)容:

keytool -list -v -keystore MyCA.jks

輸入密碼后,查看到的內(nèi)容如下:

Keystore type: JKS
Keystore provider: SUN

Your keystore contains 1 entry

Alias name: myca
Creation date: Sep 6, 2018
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=myca, OU=mallen's ca, O=mallen, L=chengdu, ST=sichuan, C=CN
Issuer: CN=myca, OU=mallen's ca, O=mallen, L=chengdu, ST=sichuan, C=CN
Serial number: 4385a752
Valid from: Thu Sep 06 14:59:31 CST 2018 until: Wed Dec 05 14:59:31 CST 2018
Certificate fingerprints:
     MD5:  6E:2F:7E:C0:FA:78:53:95:FD:1C:4D:5C:53:BF:92:30
     SHA1: CD:4E:FF:AA:91:7E:68:AD:24:39:2E:9F:1E:70:85:54:03:63:F6:A2
     SHA256: E8:85:FA:33:85:B7:E9:FE:96:BD:5E:80:CF:00:F6:B5:4A:EA:2D:F7:47:B7:81:3B:60:DF:79:1D:5E:9E:EA:A0
     Signature algorithm name: SHA256withRSA
     Version: 3

Extensions: 

#1: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 61 30 66 A2 7F B6 F1 B5   EA A1 D6 31 1B A5 DC 60  a0f........1...`
0010: 25 9E 04 28                                        %..(
]
]



*******************************************
*******************************************

B) 提取CA的公鑰文件

擁有了CA公私鑰文件之后,可以提取出CA的證書(shū)文件,該文件用戶客戶端校驗(yàn)服務(wù)器端證書(shū)時(shí)的密鑰。后續(xù)會(huì)介紹怎么使用,提取命令如下:

keytool -exportcert -keystore MyCA.jks -alias MyCA -file MyCA.crt

該命令指定從MyCA.jks密鑰對(duì)文件中獲取名稱(chēng)為MyCA的密鑰對(duì)的公鑰,并將公鑰寫(xiě)入到MyCA.crt中。

2. 模擬服務(wù)器SERVER

同樣,每個(gè)Server也會(huì)有自己的公私鑰:server.pub和server.pri。也需要首先生成公私鑰對(duì):

keytool -genkeypair -alias myserver -keyalg RSA -keysize 2048 -keystore MyServer.jks

該命令指定生成一個(gè)公私鑰對(duì),使用RAS算法,key長(zhǎng)度為2048,生成到文件MyServer.jks中,公私鑰對(duì)的名稱(chēng)為myserver。
后續(xù)的輸入與生成MyCA.jks一致,但是需要注意的是在What is your first and last name?這一項(xiàng),作為服務(wù)器應(yīng)該填寫(xiě)服務(wù)器的域名,比如www.baidu.com或者*.baidu.com。jdk中,在驗(yàn)證服務(wù)器端證書(shū)時(shí),首先會(huì)取該字段來(lái)與當(dāng)前訪問(wèn)的地址做對(duì)比,如果一致才能進(jìn)入真正的證書(shū)驗(yàn)證階段。
作為測(cè)試,建議此處輸入localhost,在后續(xù)訪問(wèn)時(shí)同樣使用localhost訪問(wèn)。如果后續(xù)方式需要使用ip,此處請(qǐng)輸入ip。

3. 證書(shū)申請(qǐng)請(qǐng)求

Server有了公私鑰對(duì)后,便可發(fā)起證書(shū)申請(qǐng)。證書(shū)申請(qǐng)時(shí),需要提交證書(shū)申請(qǐng)文件,該文件一般稱(chēng)為CSR文件。生成該文件的命令如下:

keytool -certreq -alias myserver -keystore MyServer.jks -file MyServer.csr

該命令根據(jù)MyServer.jks公私鑰對(duì)生成證書(shū)申請(qǐng)文件MyServer.csr,該文件生成后,便可提交到CA機(jī)構(gòu)進(jìn)行證書(shū)的申請(qǐng)。

4. CA頒發(fā)證書(shū)

CA機(jī)構(gòu)接收到MyServer的證書(shū)申請(qǐng)請(qǐng)求時(shí),校驗(yàn)MyServer身份通過(guò)后,就可以使用自己的私鑰對(duì)證書(shū)進(jìn)行認(rèn)證(簽名),命令如下:

keytool -gencert  -alias MyCA -keystore MyCA.jks -infile MyServer.csr -outfile MyServer.crt

該命令使用CA的公私鑰對(duì)文件MyCA.jks對(duì)證書(shū)申請(qǐng)文件MyServer.csr進(jìn)行簽名,最終生成MyServer的CA證書(shū)文件MyServer.crt。

5. 導(dǎo)入Server證書(shū)

CA機(jī)構(gòu)為MyServer頒發(fā)認(rèn)證認(rèn)證書(shū)MyServer.crt后,MyServer即可將證書(shū)文件導(dǎo)入到自己的證書(shū)庫(kù)MyServer.jks中,導(dǎo)入命令如下:

keytool -import -alias myserver -file MyServer.crt -keystore MyServer.jks -trustcacerts

該命令會(huì)將MyServer.crt證書(shū)文件導(dǎo)入到MyServer.jks證書(shū)庫(kù)中,需要注意的是,此處的alias必須與服務(wù)器公私鑰對(duì)名稱(chēng)保持一致,也就是必須為myserver。
但在導(dǎo)入時(shí),會(huì)報(bào)錯(cuò):

keytool error: java.lang.Exception: Failed to establish chain from reply

該錯(cuò)誤表示證書(shū)鏈不能建立,其原因是由于在導(dǎo)入MyServer.crt證書(shū)時(shí)會(huì)對(duì)其簽名做驗(yàn)證,以便確認(rèn)是由信任機(jī)構(gòu)CA頒發(fā)的。但是,由于SERVER端當(dāng)前并未將MyCA的證書(shū)導(dǎo)入到的信任證書(shū)列表中,導(dǎo)致拋出該錯(cuò)誤。因此,需要將MyCA.crt導(dǎo)入到受信任的證書(shū)列表中??梢灾苯訉yCA.crt導(dǎo)入到$JAVA_HOME/jre/lib/security/cacerts文件中。命令為:

keytool -import -alias MyCA -file MyCA.crt -keystore $JAVA_HOME/jre/lib/security/cacerts

導(dǎo)入之后,再運(yùn)行導(dǎo)入MyServer.crt證書(shū)的命令即可成功導(dǎo)入。導(dǎo)入時(shí)需要輸入cacerts的密碼,默認(rèn)密碼為changeit。
由該錯(cuò)誤原因可知,哪怕對(duì)于權(quán)威的CA機(jī)構(gòu),如果CA結(jié)構(gòu)的公開(kāi)證書(shū)沒(méi)有安裝到本地,同樣會(huì)報(bào)該錯(cuò)誤。

6. 配置tomcat

其實(shí)前面5步就已經(jīng)完成證書(shū)頒發(fā)過(guò)程了,但是為了驗(yàn)證證書(shū)的頒發(fā)過(guò)程沒(méi)有問(wèn)題,我們還需要將MyServer.crt使用起來(lái)。此處我們服務(wù)器端使用tomcat來(lái)提供HTTPS服務(wù),需要進(jìn)行如下配置:
打開(kāi)tomcat的配置文件$CATALINA_HOME/conf/server.xml,打開(kāi)https的配置,填入證書(shū)文件地址、密碼和證書(shū)名稱(chēng),修改后的內(nèi)容如下:


tomcat https配置

修改完成,保存啟動(dòng)tomcat即可。

  • TIPS:如果需要查看tomcat的SSL日志,可以通過(guò)配置項(xiàng)javax.net.debug來(lái)開(kāi)啟。只需要在bin目錄下創(chuàng)建一個(gè)setenv.sh腳本,并寫(xiě)入:
JAVA_OPTS="$JAVA_OPTS -Djavax.net.debug=ssl"

當(dāng)然該配置項(xiàng)還可以進(jìn)行更細(xì)粒度的控制,請(qǐng)參考:https://access.redhat.com/solutions/973783。

7. 編寫(xiě)HTTPS客戶端

有了HTTPS服務(wù)器端,我們需要驗(yàn)證客戶端是否能正確校驗(yàn)通過(guò)我們頒發(fā)的MyServer.crt。首先,我們模擬HTTPS客戶端的機(jī)器需要安裝MyCA.crt到信任證書(shū)中:

keytool -import -alias MyCA -file MyCA.crt -keystore $JAVA_HOME/jre/lib/security/cacerts

證書(shū)安裝成功后,編寫(xiě)訪問(wèn)代碼:


java實(shí)現(xiàn)的HTTPS客戶端

這段代碼會(huì)訪問(wèn)tomcat的examples項(xiàng)目中的頁(yè)面,注意訪問(wèn)地址使用的域名是localhost,該域名與MyServer.jks中的域名保持一致。如果訪問(wèn)成功,會(huì)打印如下信息:


訪問(wèn)結(jié)果

獲取到該信息后,表示我們的HTTPS通信是正確的,服務(wù)器端的證書(shū)MyServer.crt是被信任的,因?yàn)槲覀儽镜匦湃瘟薓yCA,而MyServer.crt是由MyCA頒發(fā)的。如果我們要驗(yàn)證MyServer.crt是不被信任的,我們可以卸載掉之前安裝的MyCA.crt,再次訪問(wèn)就會(huì)出現(xiàn)如下錯(cuò)誤:
javax.net.ssl.SSLHandshakeException: 
      sun.security.validator.ValidatorException: 
        PKIX path building failed: 
          sun.security.provider.certpath.SunCertPathBuilderException: 
            unable to find valid certification path to requested target

該錯(cuò)誤的原因是服務(wù)器的證書(shū)不能被正確的驗(yàn)證,也就是通過(guò)JDK默認(rèn)的信任證書(shū)不能驗(yàn)證MyServer的證書(shū)。
如果想校驗(yàn)不通過(guò)的情況,可以通過(guò)命令刪除jdk中的MyCA.crt,命令如下:

keytool -delete -alias MyCA -keystore $JAVA_HOME/jre/lib/security/cacerts

總結(jié)

本文通過(guò)使用jdk自帶的keytool工具,模擬了服務(wù)器端CA證書(shū)的頒發(fā)過(guò)程。如果在項(xiàng)目中暫時(shí)不能在受信任的CA機(jī)構(gòu)申請(qǐng)到證書(shū),但是卻需要開(kāi)啟HTTPS功能,可以使用該文中介紹的方式來(lái)自己頒發(fā)CA證書(shū)。另外,通過(guò)這種方式,就可以在家自己進(jìn)行HTTPS相關(guān)的技術(shù)研究了。
本文是HTTPS那些事兒系列的最后一篇文章,如需查看本系列其他文章,請(qǐng)轉(zhuǎn)至前言。
本人程序猿一枚,語(yǔ)言能力有限,本系列的文章是在工作過(guò)程中積累而來(lái)的,原意僅供自己備忘?,F(xiàn)公開(kāi)出來(lái),也僅是想幫助有需要的人,如有問(wèn)題,可隨時(shí)留言,如果我懂我會(huì)不定期回復(fù)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容