keytool是一个java数据证书的管理工具。keytool将密钥和证书存在一个称为keystore(即密钥库)的文件中。在keystore里,包含两种数据——KeyEntry和CertEntry,KeyEntry包含私钥和证书,CertEntry只包含证书。keystore中可以有多个Entry(即条目),在库里的每个Entry都是靠别名来识别的。
keytool不需要额外安装,是jdk自带的一个工具,其位置位于jre的bin目录,只需要在path环境变量里加上jre的bin目录即可使用(比如我的路径是“G:\jdk1.7.0_45\jre\bin”)。
配置好环境变量后敲“keytool”后就能看到keytool支持的指令以及怎么查看某个指令具体的用法。
比如我想知道genkeypair指令的具体用法,就可以输入“keytool -genkeypair -help”。
接下来介绍keytool常用的一些指令,掌握了这些指令基本上就能完成日常的开发工作。而且只要你掌握了这几个常用指令的写法,对于没有介绍到的指令相信你也能够自己写出来。
1.生成密钥对
keytool -genkeypair -alias demo1 -keystore demo.jks -validity 36500 -keyalg ec
(别名为demo1,keystore的名称为demo.jks,有效期为36500天,密钥算法为ECDSA)
在生成密钥对的时候需要填写一些必要的信息,填写完毕后在当前目录下就会生成一个名为demo.jks的密钥库文件,该密钥库文件里有一个别名为demo的条目,密钥对的信息就保存在该条目里(如果当前目录下已经有了名为demo.jks的文件,则会直接在demo.jks中新增一个名为demo1的条目)。另外此处并不只是生成了密钥对,它会同时对公钥进行包装生成自签名的证书。所以demo条目下其实保存的是一个私钥和一个自签名证书。(请注意,此处填写了两个密码:一个是密钥库的密码,另一个是条目demo1的密码。此过程中只要用到密码的地方我都会设置为123456。)
2.查看密钥库信息
keytool -list -keystore demo.jks
我们可以给keytool -list命令添加-v选项来看到更加详细的内容。
keytool -list -v -keystore demo.jks
可以看到此时密钥库中只有一个名为demo1的条目,但前面说过,一个密钥库里面是可以存放多个条目的,让我们再生成一个名为demo2的条目看一下。
keytool -genkeypair -alias demo2 -keystore demo.jks
按提示完成操作后,keystore中就会多了一个名为demo2的条目,密钥库中条目的个数也变成了2,如下:
比较细(lan)心(duo)的同学可能会发现一个问题,每次对密钥库的操作都需要输入密钥库的密码!那么有没有办法不输入密钥库的密码呢?很显然,有的!我们可以添加选项-storepass来直接在命令行中输入密钥库的密码。
keytool -list -keystore demo.jks -storepass 123456
3.导出证书
keytool -exportcert -alias demo1 -file demo1.cer -keystore demo.jks -storepass 123456
(将demo.jks中demo1条目的证书导出到demo1.cer文件中)
执行命令后我们就可以在当前目录下看到一个名为demo1.cer的文件:
4.查看证书内容
keytool -printcert -file demo1.cer
5.导入证书
keytool -importcert -alias demo1cert -file demo1.cer -keystore demo.jks -storepass 123456
由于demo1.cer证书是从demo.jks中的demo1条目中导出来的,所以此处给出了提示“在别名之下,证书已经存在于密钥库中,是否仍要添加 ?”。此处我选择了仍要添加,接下来让我们再看一下现在密钥库中的信息:
可以看到,现在密钥库中有了三个条目,名字分别为demo1、demo1cert和demo2。细心(这次是真的细心)的同学应该发现了一个不同之处——demo1cert条目的类型是“trustedCertEntry”,而其他两个条目的类型是“PrivateKeyEntry”。不知道大家对我在前文中提到的这句话“在keystore里,包含两种数据——KeyEntry和CertEntry ”还有没有印象,聪明的同学可能已经想到了。没错,CertEntry指的就是“trustedCertEntry”,这种条目下只包含证书;KeyEntry指的就是“PrivateKeyEntry”,这种条目下不仅有证书信息,还包含私钥。
看到这里,有些同学可能会产生迷惑:“你说KeyEntry和CertEntry含有证书我们可以理解,因为我们确实看到了有关证书的描述(虽然也看不懂啥意思)。但是KeyEntry下怎么就包含私钥信息了,从来没看到过任何和私钥有关的信息啊? ”。嘿嘿,大家有这种困惑很正常,因为从头到尾我们确实没看到过私钥长什么样。那么为了解除大家的这种困惑,接下来就让我们一起来看一下私钥到底长什么样!
6.如何从jks文件中获取私钥信息
由于keytool确实没有提供给大家导出私钥的方法,所以我们不得不借助另外一个工具——openssl。
因为jks是java自己搞出来的东西,所以openssl不支持jks类型的密钥库,那么要想使用openssl,我们只好先把jks类型的密钥库转成一个大家都支持的类型——pkcs12:
keytool -importkeystore -srckeystore demo.jks -srcalias demo1 -srcstorepass 123456 -destkeystore demo1.p12 -deststoretype pkcs12 -deststorepass 123456
执行完此条命令后,当前目录下会生成demo1.p12的文件,由于该文件的格式是der,打开看是二进制格式不可读,所以我们需要把此文件的格式转成pem。而keytool无法完成此功能,我们只好借助openssl来完成:
openssl pkcs12 -in demo1.p12 -out demo1.pem -passin pass:123456 -passout pass:123456
执行完此条命令后,当前目录下会生成一个demo1.pem的文件,此时可以直接用文本打开,内容如下:
其中“-----BEGIN ENCRYPTED PRIVATE KEY-----”至“-----END ENCRYPTED PRIVATE KEY-----”中间的内容就是加密后的私钥信息(相信大家也能从中找到证书的信息)。什么?加密后的私钥信息也满足不了你?好吧,我们就来看下没有经过加密的私钥。
首先将“-----BEGIN ENCRYPTED PRIVATE KEY-----”至“-----END ENCRYPTED PRIVATE KEY-----”的文本复制到一个新的文件demo1.key中,如下图所示:
然后执行命令“openssl ec -in demo1.key”(如果使用的算法不是ecdsa就把ec换成对应算法的简写),输入密码“123456”即可得到最终的私钥!
最后再给大家一点提示,此处我只导出了别名为demo1的私钥和证书信息,实际上你不指定别名时可以导出整个密钥库的私钥和证书信息!具体怎么导出请自己尝试。
7.总结——使用到的所有命令
keytool -genkeypair -alias demo1 -keystore demo.jks -validity 36500 -keyalg ec
keytool -list -keystore demo.jks
keytool -list -v -keystore demo.jks
keytool -genkeypair -alias demo2 -keystore demo.jks
keytool -list -keystore demo.jks -storepass 123456
keytool -exportcert -alias demo1 -file demo1.cer -keystore demo.jks -storepass 123456
keytool -printcert -file demo1.cer
keytool -importcert -alias demo1cert -file demo1.cer -keystore demo.jks -storepass 123456
keytool -importkeystore -srckeystore demo.jks -srcalias demo1 -srcstorepass 123456 -destkeystore demo1.p12 -deststoretype pkcs12 -deststorepass 123456
openssl pkcs12 -in demo1.p12 -out demo1.pem -passin pass:123456 -passout pass:123456
openssl ec -in demo1.key