Java-Keytool


配置https或socket-ssl時等需要用到證書,如果公司沒有正規證書,則需要生成自簽名證書,以下介紹兩種方法。我自己配置nginx https用openssl, socket 加入ssl用Java的keytool。

## java 證書工具keytool生成自簽名證書和自簽CA證書 

jdk自帶的證書管理工具叫keytool,在jdk/bin目錄下,可以用來生成自簽名證書、導入導出證書、打印證書信息等。

### 1. 名詞

自簽名證書:用自己的私鑰簽發自己的公鑰即主體信息生成的證書。
證書簽名:對證書固定值進行hash后用密鑰對中的私鑰對hash值加密
keystore:  keytool生成證書的存儲庫,用來存儲若干條目,每一條目包含公私鑰,主體信息等。默認為用戶目錄下.keystore,相當於一個有密碼保護的文件。
truststore: 與keystore格式相同,只是為區分keystore用來存放信任的證書的新的庫,不存密鑰等信息。

der:證書編碼格式,證書結構體轉換為二進制格式。
pem:證書編碼格式,對der二進制編碼的base64字符,包含---begin---,----end----。// 命令中加-rfc可打印和生成此類文件
.csr:證書請求文件格式,包含公鑰和主體信息,發給ca,ca用私鑰對內容簽名並制作成證書返回。keytool在生成csr文件時需要指定證書(即公鑰與主體信息)。
.crt:一般用於linux系統的證書格式,包含公鑰和主體信息。 .cer:一般用於windows的證書文件格式,包含公鑰和主體信息。 .p12:證書交換格式,包含公鑰私鑰(私用密碼加密),用於交換傳輸。

 

### 2.具體使用

可以以一個完整例子來了解keytool命令。在socket或http協議傳輸數據時,如需加密傳輸會話內容,會在TCP上加上ssl/tls,http則改為https協議。此時服務端需要給客戶端提供證書以供客戶端驗證並協商會話密鑰,如果沒有正規CA簽發的證書,則需自簽名。

> 客戶端用簽發證書的根證書驗證,如果是自簽名一級證書,則客戶端需內置此自簽名證書,如果是自簽名二級證書,則用簽發它的跟證書驗證

- 生成自簽名證書

keytool -genkeypair -alias golove -keysize 2048 -keyalg RSA -validity 3650 -keystore teststore.jks -storetype JKS
 
- genkeypair:生成公私鑰對條目,私鑰不可見,公鑰會以證書格式保存在keystore中。
- alias: 指定別名,區分不同條目,默認mykey
- keysize: 密鑰長度
- keyalg: 公私鑰算法
- validity: 證書過期時間
- keystore: 指定存儲密鑰庫,若不存在會創建,若指定則在當前文件夾下生成。默認密鑰庫為用戶目錄下.keystore文件
- storetype: 密鑰庫類型  JKS PKCS等

  > 輸入密鑰庫密碼和本條目密碼都為123456,以及其他主體信息會生成密鑰對保存在teststore.jks中。公鑰以證書格式保存,帶有主體信息。此時證書庫中可以看到公鑰信息(私鑰無法打印)
  >
  > 第一條主體信息:您的姓名與姓氏中填入服務器域名的完整信息而非name,如:www.golove.com。

- 導出自簽名證書

// 如果要生成pem編碼格式的證書直接加上 -rfc參數即可,證書詳細信息格式用 -v
keytool -export -alias golove -keystore teststore.jks -file golove.crt

> 現在可以將此證書分發給客戶端了,客戶端做相應配置,驗證域名或直接跳過驗證(因為是用它自身公鑰驗證,不能保證安全性,一般默認信任),使用此證書與服務端交換隨機數。


接下來稍微了解下keystore內容並生成一個根證書來簽發二級證書。

 

- 查看keystore中證書條目列表

keytool -list -v -keystore teststore.jks




  再看下剛才根據此條目導出的自簽證書,導出后已經包含了公鑰等其他信息形成了完整證書,但注意verifiedby字段(簽發者常用名)還是自己


- 生成證書簽名請求(CSR文件)

keytool -certreq -alias golove -keystore teststore.jks -file temp_go_love.csr

  > 用keystore中golove條目生成了證書簽名請求文件temp_go_love.csr,內包含golove條目的公鑰和主體信息,將證書簽名請求文件發給正規CA,CA用私鑰對公鑰和信息簽名后制作成證書文件返回就可以使用了。正規CA的公鑰瀏覽器內置,所以此時瀏覽器可以驗簽名成功。
  >
  > 但我們要自己模擬CA簽發二級證書,CA也是要有公私鑰對,所以先生成CA密鑰對。

- 生成一個自簽名證書作為CA根證書,名字與姓氏選項這里填入root

keytool -genkeypair -alias rootca -keysize 2048 -keyalg RSA -validity 3650 -keystore teststore.jks -storetype JKS

- 使用CA證書給golove證書簽名,即用CA的私鑰簽名后與golove的公鑰生成一個證書

keytool -gencert -alias rootca -keystore teststore.jks -infile temp_go_love.csr -outfile golove_new.crt

此時已經生成了一個golove_new.crt的二級證書,以文件形式打開golove.crt和golove_new.crt兩個證書文件對比下內容。


golove.crt:



golove_new.crt



> 可以看到簽發者已經變成root,公鑰等其他信息不變,但簽名值變了,說明已經用新的私鑰(root私鑰)替換原有(golove)簽名,在證書信任連上序號為2,此即二級證書。

- 將二級證書導回teststore庫中,並且直接替換原有別名為golove的條目

keytool -import -v -alias golove -file golove_new.crt -keystore teststore.jks

再次打印證書庫中條目列表可以看到別名為golovet的條目證書鏈變為2,發布者變為root.

> 此時可以將root證書導出給客戶端內置,服務端綁定二級證書,這樣客戶端驗證時可以用根證書驗證二級證書。其實大部分程序直接使用一級的自簽名證書即可,但若需要雙向驗證,服務端驗證客戶端時不同客戶端最好使用服務端的rootca私鑰來簽發,這樣服務端可以直接用一個rootca的證書驗證。實現了動態擴展且客戶端的證書不同。  ​

- 為了區分teststore,可以新建一個只放信任證書,不存儲密鑰的倉庫。將剛才的rootca證書和golove二級證書導入一個新倉庫(如果為了方便,也可以直接用一個密鑰庫,不需要此庫

// 從teststore導出rootca證書
keytool -export -alias rootca -keystore teststore.jks -file rootca.crt
// 導入rootca證書到新庫
keytool -import -v -file rootca.crt -alias rootca -keystore truststore.jks
// 導入golove證書到新庫
keytool -import -v -file golove_new.crt -alias golove -keystore truststore.jks

 

keytool 常用命令:

// 以rfc模式打印,即base64可見字符,與pem編碼格式一樣。 -v為詳細輸出
keytool -printcert -rfc -file rootca.ctr
// 查看證書庫中證書條目列表 詳細信息
keytool -list -v -keystore teststore.jks
// 將證書庫中的條目導出為證書文件,如要生成可見字符編碼格式的證書文件 加上 -rfc 參數即可。
keytool -export -alias rootca -keystore teststore.jks -file rootca.ctr
// 刪除密鑰庫中的條目
keytool -delete -alias rootca -keystore teststore.keystore
// 修改證書庫密碼,輸入舊密碼或加參數 -storepass 111111
keytool -storepasswd -new 123456 -keystore truststore
// 修改某條目密碼
keytool -keypasswd -alias myCA -keypass 654321 -new newpass -storepass 123456 -keystore myCALib


還有一個問題,keytool不能打印出密鑰對中的私鑰,用-list查看密鑰庫列表也沒有完整的私鑰信息。要獲取私鑰,可以在java程序中加載密鑰庫,用jdk KeyStore類的相關方法獲取到公私鑰信息,然后做加解密的驗證等。

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

## openssl生成證書

由於是給nginx配置https用的,我先在nginx目錄下創建一個文件夾。

$sudo mkdir -p /etc/nginx/conf.d/ssl/
$cd /etc/nginx/config.d/ss

- 創建秘鑰

openssl genrsa -des3 -out server1.key

輸入123456密碼創建一個rsa私鑰。(此處des3與公私鑰對無關。)可以打印查看以下對應的公鑰。 openssl rsa -in server1.key -pubout 

- 創建請求文件

sudo openssl req -new -key server1.key -out server1.cs
輸入密碼123456后回車 依次填寫主體信息,大部分可以直接回車略過
Country Name (2 letter code) [AU]:CN
State or Province Name (full name) [Some-State]:zhejiang
Locality Name (eg, city) []:hangzhou
Organization Name (eg, company) [Internet Widgits Pty Ltd]:flk
Organizational Unit Name (eg, section) []:flk-test
Common Name (e.g. server FQDN or YOUR name) []: // 這里可以填寫服務器對應域名,否則瀏覽器警告
Email Address []:

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

- 刪除私鑰中的密碼

由於生成私鑰時指定了des3密碼,每次使用私鑰都要輸入密碼,比較麻煩,這里刪除掉。

openssl rsa -in server1.key -out server1.key

- 生成證書

openssl x509 -req -days 3650 -in server1.csr -signkey server1.key -out server1.crt

可以看到是用自己的私鑰簽發的主體信息。生成證書后可以刪除crt了。

此時有私鑰server1.key和自簽名證書server1.crt。如果nginx代理https請求,只要指定此目錄對應文件即可。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM