本章是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和客戶(hù)端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)的客戶(hù)端會(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文件的訪(fǎng)問(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ū)文件奄抽,該文件用戶(hù)客戶(hù)端校驗(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)前訪(fǎng)問(wèn)的地址做對(duì)比焊虏,如果一致才能進(jìn)入真正的證書(shū)驗(yàn)證階段。
作為測(cè)試秕磷,建議此處輸入localhost诵闭,在后續(xù)訪(fǎng)問(wèn)時(shí)同樣使用localhost訪(fǎng)問(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ū)列表中⊥旅啵可以直接將MyCA.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)容如下:
修改完成厦滤,保存啟動(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客戶(hù)端
有了HTTPS服務(wù)器端添瓷,我們需要驗(yàn)證客戶(hù)端是否能正確校驗(yàn)通過(guò)我們頒發(fā)的MyServer.crt梅屉。首先,我們模擬HTTPS客戶(hù)端的機(jī)器需要安裝MyCA.crt到信任證書(shū)中:
keytool -import -alias MyCA -file MyCA.crt -keystore $JAVA_HOME/jre/lib/security/cacerts
證書(shū)安裝成功后鳞贷,編寫(xiě)訪(fǎng)問(wèn)代碼:
這段代碼會(huì)訪(fǎng)問(wèn)tomcat的examples項(xiàng)目中的頁(yè)面坯汤,注意訪(fǎng)問(wèn)地址使用的域名是localhost,該域名與MyServer.jks中的域名保持一致搀愧。如果訪(fǎng)問(wèn)成功惰聂,會(huì)打印如下信息:
獲取到該信息后,表示我們的HTTPS通信是正確的咱筛,服務(wù)器端的證書(shū)MyServer.crt是被信任的搓幌,因?yàn)槲覀儽镜匦湃瘟薓yCA,而MyServer.crt是由MyCA頒發(fā)的迅箩。如果我們要驗(yàn)證MyServer.crt是不被信任的溉愁,我們可以卸載掉之前安裝的MyCA.crt,再次訪(fǎng)問(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)的,原意僅供自己備忘》绯樱現(xiàn)公開(kāi)出來(lái)鳖目,也僅是想幫助有需要的人,如有問(wèn)題缤弦,可隨時(shí)留言领迈,如果我懂我會(huì)不定期回復(fù)。