Skip to content

keytool 生成证书

.jks 和 .keystore 密钥库文件

jks 和 keystore 都是密钥库,可以用来存储证书和私钥。在 java 中一般使用 jks 密钥库,二者功能一样,可以互相转换。

.crt 和 .cer 证书文件

  • .crt:扩展名 CRT 用于证书。证书可以是 DER 编码,也可以是 PEM 编码。扩展名 CER 和 CRT 几乎是同义词。这种情况在各种 unix/linux 系统中很常见。
  • .cer:CRT 证书的微软型式。可以用微软的工具把 CRT 文件转换为 CER 文件(CRT 和 CER 必须是相同编码的,DER 或者 PEM)。扩展名为 CER 的文件可以被 IE 识别并作为命令调用微软的 cryptoAPI(具体点就是 rudll32.exe

keytool -help

bash
PS C:\Source> keytool -help
密钥和证书管理工具
命令:
 -certreq            生成证书请求
 -changealias        更改条目的别名
 -delete             删除条目
 -exportcert         导出证书
 -genkeypair         生成密钥对
 -genseckey          生成密钥
 -gencert            根据证书请求生成证书
 -importcert         导入证书或证书链
 -importpass         导入口令
 -importkeystore     从其他密钥库导入一个或所有条目
 -keypasswd          更改条目的密钥口令
 -list               列出密钥库中的条目
 -printcert          打印证书内容
 -printcertreq       打印证书请求的内容
 -printcrl           打印 CRL 文件的内容
 -storepasswd        更改密钥库的存储口令

使用 "keytool -command_name -help" 获取 command_name 的用法

keytool -genkeypair -help

bash
PS C:\Source> keytool -genkeypair -help
keytool -genkeypair [OPTION]...
生成密钥对
选项:
 -alias <alias>                  要处理的条目的别名
 -keyalg <keyalg>                密钥算法名称(当使用 -genkeypair 参数时可选为 RSA DSA)
 -keysize <keysize>              密钥位大小
 -sigalg <sigalg>                签名算法名称
 -destalias <destalias>          目标别名
 -dname <dname>                  唯一判别名(CN:名字与姓氏(域名); OU:组织单位名称; O:组织名称; L:城市或区域名称; ST:省/市/自治区名称; C:该单位的双字母国家/地区代码)
 -startdate <startdate>          证书有效期开始日期/时间
 -ext <value>                    X.509 扩展
 -validity <valDays>             有效天数(默认大约90天)
 -keypass <arg>                  密钥口令
 -keystore <keystore>            密钥库名称
 -storepass <arg>                密钥库口令
 -storetype <storetype>          密钥库类型(常用的有JKS(默认),JCEKS,PKCS12(行业标准推荐),BKS,UBER 等。
                                 KeyStore 的类型并不要求在文件名上体现,但是使用者要明确所使用的KeyStore的格式)
 -providername <providername>    提供方名称
 -providerclass <providerclass>  提供方类名
 -providerarg <arg>              提供方参数
 -providerpath <pathlist>        提供方类路径
 -v                              详细输出
 -protected                      通过受保护的机制的口令
使用 "keytool -help" 获取所有可用命令

KeyStore 和 TrustStore

  • KeyStore 是服务器的密钥存储库,存服务器的公钥私钥证书
  • TrustStore 是服务器的信任密钥存储库,存 CA 公钥,但有一部分人存的是客户端证书集合,这样并不合适

错误的使用:把 KeyStore 和 TrustStore 做成同一个 JKS 文件或 PKCS12 文件。通过导入客户端证书来实现验证客户端证书。实际生产中并不能这么做,客户端有成千上万个,你不可能都去导吧。

因为 KeyStore 和 TrustStore Java 中都可以通过 keytool 来管理的,所以在使用时多有混淆。记住以下几点,可以最大限度避免这些混淆:

  • 如果要保存你自己的密码,秘钥和证书,应该使用 KeyStore,并且该文件要保持私密不外泄,不要传播该文件;
  • 如果要保存你信任的来自他人的公钥和证书,应该使用 TrustStore,而不是 KeyStore;
  • 在以上两种情况中的文件命名,要尽量提示其安全敏感程度而不是有歧义或者误导
  • 比如使用 KeyStore 的场景把文件命名为 truststore.jks, 或者该使用 TrustStore 的情况下把文件命名为 keystore.jks 之类,这些用法都属于严重误导随后的使用者,有可能把比较私密的文件泄露出去;
  • 拿到任何一个这样的文件时,确认清楚其内容然后决定怎样使用;
  • 因为 KeyStore 文件既可以存储敏感信息,比如密码和私钥,也可以存储公开信息比如公钥,证书之类,所有实际上来讲,可以将 KeyStore 文件同样用做 TrustStore 文件, 但这样做要确保使用者很明确自己永远不会将该 KeyStore 误当作 TrustStore 传播出去。

一个 TrustStore 仅仅用来包含客户端信任的证书,所以,这是一个客户端 “所信任的来自其他人或者组织的信息” 的存储文件,而不能用于存储任何安全敏感信息,比如私钥(private key)或者密码。

客户端通常会包含一些大的 CA 机构的证书,这样当遇到新的证书时,客户端就可以使用这些 CA 机构的证书来验证这些新来的证书是否是合法的。

生成 Keystore 文件

bash
# 不能单纯的生成一个密钥库,生成密钥库的时候必须同时生成一个条目。下面这个命令在当前工作目录生成了一个密钥库文件 keystore.jks,里面存储了一个别名为 mengweijin 的密钥对
# 生成服务端密钥 jks 文件。注意:-storetype jks 参数,如果配置为 JKS,则在 SpringBoot 中也需要配置为对应的类型:key-store-type: JKS
# 在cmd中执行JDK中keytool的命令,创建一个文件名为 keystore.jks,别名为 mengweijin 的密钥库:
keytool -genkeypair -alias mengweijin -validity 36500 -keyalg RSA -dname "CN=mengweijin.com,OU=com.mengweijin,O=mengweijin,L=xi an,ST=shan xi, C=CN" -keypass 123456 -storepass 123456 -storetype JKS -keystore keystore.jks

Warning:
# 由于我们是在 SpringBoot 中配置 JKS 格式的密钥库,因此,不必按照下面的告警信息迁移到 PKCS12(.p12) 格式。如果需要迁移到 p12 格式,按照提示执行命令即可。
JKS 密钥库使用专用格式。建议使用 "keytool -importkeystore -srckeystore keystore.jks -destkeystore keystore.jks -deststoretype pkcs12" 迁移到行业标准格式 PKCS12。
PS C:\Source>
# 到这里已经在命令行执行目录下生成了 keystore.jks 密钥库文件。

使用 openssl 查看公钥

安装 openssl(如果电脑上已经安装过了,就可以跳过)

URL: http://slproweb.com/products/Win32OpenSSL.html

安装完成后,配置环境变量。把 openssl 安装路径 bin 的路径(例如 C:\Program Files\OpenSSL-Win64\bin)加入到操作系统的系统环境变量 Path 中。

关闭当前 cmd 窗口,或者重启电脑,重新打开一个 cmd,此时 openssl 命令就可以直接使用了。

查看公钥

bash
# 执行查看公钥的命令:
keytool -list -rfc --keystore keystore.jks -storepass 123456 | openssl x509 -inform pem -pubkey
# 生成的公钥(-----BEGIN PUBLIC KEY----- 和 -----END PUBLIC KEY----- 之间的是公钥,包括这两个头和尾)

keytool -v -importkeystore 密钥库格式类型转换

bash
# .jks 转 .p12 格式
keytool -v -importkeystore -srcstoretype JKS -srckeystore keystore.jks -srcstorepass 123456 -srcalias mengweijin -srckeypass 123456 -deststoretype PKCS12 -destkeystore keystore.p12 -deststorepass 123456 -destalias mengweijin -destkeypass 123456
# .jks 转 .keystore 同理,只是这个参数依然是这样:-deststoretype JKS
# 另外,所有 .keystore 与 .p12 之间的转换跟 .jks 与 .p12 之间的转换参数完全一样。

.p12 导出私钥文件( .key)

bash
# .key 文件不能通过 keytool 导出,只能通过代码或者 openssl 等工具导出。
openssl pkcs12 -in keystore.p12 -nocerts -nodes -out mengweijin.key -password pass:123456

PS C:\Source> openssl pkcs12 -help
Usage: pkcs12 [options]
Valid options are:
 -nokeys             Don't output private keys
 -nodes              Don't encrypt private keys
 -in infile          Input filename
 -out outfile        Output filename
 -password val       Set import/export password source
 ...... 这里省略了其他命令帮助信息

.jks 导出证书文件( .cer 或者 .crt )

bash
# 导出 .crt
keytool -v -export -alias mengweijin -keystore keystore.jks -storepass 123456 -rfc -file mengweijin.crt
# 导出 .cer
keytool -v -export -alias mengweijin -keystore keystore.jks -storepass 123456 -rfc -file mengweijin.cer
# 注意:.keystore 同理。