JDK11中,默認的密鑰庫類型為 PKCS12,它不支持單獨給單個密鑰設置密碼,只支持給密鑰庫設置密碼,而之前的 JKS 密鑰庫可以支持單獨給每個密鑰設置密碼。
默認的密鑰庫位置是 JavaHome 下的 ./lib/security/cacerts,查看默認密鑰庫的密鑰:
./bin/keytool -list -keystore ./lib/security/cacerts
首先看一下 keytool 命令的參數有哪些?
# 使用 OHMYZSH 提示的 ➜ ~ keytool - -J -- specify java option -alias -- alias -certreq -- command to generate certificate signing request -delete -- command to delete entry -dest -- destination alias -dname -- X.500 distinguish name -export -- command to store certificate -file -- specify certificate file -file -- specify certificate signing request file -file -- specify identity database file -genkey -- command to generate a key pair -help -- command to print help message -identitydb -- command to read identity database -import -- command to import certificate or certificate chain -keyalg -- key algorithm -keyclone -- command to create new keystore entry -keypass -- old password for private key -keypass -- password for private key -keypasswd -- command to change password for private key -keysize -- key size -keystore -- keystore location -list -- command to print keystore entry -new -- new password -new -- nwe password for private key -new -- password for private key of new entry -noprompt -- disable interaction with the user -printcert -- command to print certificate in a human-readable format -rfc -- make certificate format printable as RFC 1421 -selfcert -- command to generate X.509 v1 self-signed certificate -sigalg -- signature algorithm -storepass -- password for keystore -storepasswd -- command to change password for keystore -storetype -- keystore type -trustcacerts -- use cacerts -v -- make certificate format human-readable -v -- verbose mode -validity -- valid days ➜ ~ keytool --help 密鑰和證書管理工具 命令: -certreq 生成證書請求 -changealias 更改條目的別名 -delete 刪除條目 -exportcert 導出證書 -genkeypair 生成密鑰對 -genseckey 生成密鑰 -gencert 根據證書請求生成證書 -importcert 導入證書或證書鏈 -importpass 導入口令 -importkeystore 從其他密鑰庫導入一個或所有條目 -keypasswd 更改條目的密鑰口令 -list 列出密鑰庫中的條目 -printcert 打印證書內容 -printcertreq 打印證書請求的內容 -printcrl 打印 CRL 文件的內容 -storepasswd 更改密鑰庫的存儲口令 使用 "keytool -?, -h, or --help" 可輸出此幫助消息 使用 "keytool -command_name --help" 可獲取 command_name 的用法。 使用 -conf <url> 選項可指定預配置的選項文件。
后面跟着英文注釋,可以簡單看一下。
如何生成密鑰?
➜ ~ keytool -genkey -alias "key-1" -keystore "/Users/wu/java-key.keystore" -storepass 123456 您的名字與姓氏是什么? [Unknown]: ZhangSan 您的組織單位名稱是什么? [Unknown]: Home-1 您的組織名稱是什么? [Unknown]: Home-2 您所在的城市或區域名稱是什么? [Unknown]: Beijing-1 您所在的省/市/自治區名稱是什么? [Unknown]: Beijing-2 該單位的雙字母國家/地區代碼是什么? [Unknown]: CN CN=ZhangSan, OU=Home-1, O=Home-2, L=Beijing-1, ST=Beijing-2, C=CN是否正確? [否]: 是
執行完后會自動創建 java-key.keystore 這個文件,並且密鑰庫的密碼是 123456,剛剛生成的密鑰別名是 key-1。
執行命令后會讓你填寫一些信息,這些信息竟然可以隨便填,沒有校驗。
查看密鑰庫里有哪些密鑰?
➜ ~ keytool -keystore "/Users/wu/java-key.keystore" -storepass 123456 -list -v 密鑰庫類型: PKCS12 密鑰庫提供方: SUN 您的密鑰庫包含 1 個條目 別名: key-1 創建日期: 2021年1月25日 條目類型: PrivateKeyEntry 證書鏈長度: 1 證書[1]: 所有者: CN=ZhangSan, OU=Home-1, O=Home-2, L=Beijing-1, ST=Beijing-2, C=CN 發布者: CN=ZhangSan, OU=Home-1, O=Home-2, L=Beijing-1, ST=Beijing-2, C=CN 序列號: 32ddf5c6 生效時間: Mon Jan 25 10:16:52 CST 2021, 失效時間: Sun Apr 25 10:16:52 CST 2021 證書指紋: SHA1: 5A:22:06:04:E9:95:3A:BA:13:9B:52:F7:85:CD:E7:DF:87:27:F7:EB SHA256: D8:0D:0C:71:51:9E:B0:1F:1B:58:F8:0D:0B:00:28:B3:05:48:30:4C:FF:D9:F1:33:0F:E4:4C:16:24:22:6E:1E 簽名算法名稱: SHA256withDSA 主體公共密鑰算法: 2048 位 DSA 密鑰 版本: 3 擴展: #1: ObjectId: 2.5.29.14 Criticality=false SubjectKeyIdentifier [ KeyIdentifier [ 0000: 80 F7 D4 98 2F 5E 93 6C D8 5A D7 3C 9B B2 CB 1F ..../^.l.Z.<.... 0010: D6 96 66 EC ..f. ] ] ******************************************* *******************************************
可以發現,默認的密鑰庫類型是 PKCS12,可以通過 -storetype 來指定(如:-storetype JKS),默認的證書有效期是三個月,可以通過 -validity 來指定(如:-validity 180),默認的簽名算法是 DES(SHA256withDSA),可以通過 -keyalg 來指定(如:-keyalg RSA,RSA默認的簽名算法是 SHA256withDSA),其中的密鑰長度可以使用 -keysize 參數來指定(如:-keyalg RSA -keysize 512,密鑰算法有各自的密鑰長度,不能隨便指定)。
如果選擇其它密鑰,必須得保證在 KeyPairGenerator 中可用,比如 SHA512WITHRSA 就不可用,報錯信息還挺友好。
➜ ~ keytool -genkey -alias "key-3" -keystore "/Users/wu/java-key.keystore" -storepass 123456 -keyalg SHA512WITHRSA keytool 錯誤: java.security.NoSuchAlgorithmException: SHA512WITHRSA KeyPairGenerator not available
如何非交互式的生成密鑰?
keytool -genkey -alias "key-4" -keystore "/Users/wu/java-key.keystore" -storepass 123456 -dname "CN=ZhangSan, OU=Home-1, O=Home-2, L=Beijing-1, ST=Beijing-2, C=CN"
只需要用 -dname 參數將交互的數據填入即可。
如何刪除密鑰?
keytool -delete -alias "key-4" -keystore "/Users/wu/java-key.keystore" -storepass 123456
只需要把 -genkey 替換為 -delete,然后指定要刪除的 key 的別名即可。密鑰庫的位置和密碼是必須指定的。
如何導出證書?
➜ ~ keytool -export -alias "key-4" -keystore "/Users/wu/java-key.keystore" -storepass 123456 -file "/Users/wu/key-4.cer"
默認導出的密鑰格式為二進制格式,可以使用 -rfc 進行指定為文本格式,后綴名沒有要求,但是默認二進制格式的使用 .cer 或 .der 后綴,文本格式的使用 .crt 后綴。
如何導入證書?
keytool -import -alias key-4 -keystore ./key.keystore -file ./key-4.cer -storepass 123456
然后交互式提示你是否信任該證書,你可以使用 -noprompt 參數來直接確認導入。
導入后,證書列表如下:
key-3, 2021年1月25日, PrivateKeyEntry, 證書指紋 (SHA-256): 5A:D1:33:40:3A:52:3A:E2:62:61:6E:72:0F:E0:94:DE:D4:A9:FF:86:D9:DB:A7:BE:1A:4F:FE:B6:12:D1:1E:2C key-4, 2021年1月26日, trustedCertEntry, 證書指紋 (SHA-256): 24:B6:5A:8E:B7:6F:73:54:E8:6C:E8:76:68:50:82:36:F5:5E:56:56:91:F9:50:99:45:52:B0:95:CF:24:86:1C
可以發現默認生成的是 PrivateKeyEntry,導入的是 trustedCertEntry,分別是什么意思呢?
參看Java源碼的 java.security.KeyStore.Entry 類,發現它的實現類有三個:
- java.security.KeyStore.PrivateKeyEntry:存放一個加密的非對稱加密的私鑰,他還附帶一個對應的公鑰的證書鏈。是可以通過keytool -export命令導出對應證書。
- java.security.KeyStore.SecretKeyEntry:存放一個加密的對稱加密的密鑰。
- java.security.KeyStore.TrustedCertificateEntry:存放受信任的證書。
轉換密鑰庫類型:JKS 轉 PKCS12
keytool -importkeystore -srckeystore /Users/wu/java-key.keystore -destkeystore /Users/wu/java-key.keystore -srcstoretype jks -deststoretype pkcs12
反過來也可以
keytool -importkeystore -srckeystore /Users/wu/java-key.keystore -destkeystore /Users/wu/java-key.keystore -srcstoretype pkcs12 -deststoretype jks
PKCS12密鑰庫生成 pem 證書:
openssl pkcs12 -in java-key.keystore -out java-key.pem -password pass:123456 -passin pass:123456 -passout pass:123456
注意:密鑰庫 java-key.keystore 中可以有多個密鑰,但是生成的 java-key.pem 中只包含了密鑰庫中的第一個密鑰。
可以學習一下 openssl,對於加密解密來說很強大。