如何用keytool工具导入私有密钥和自签发证书?

开发时我们常常使用JDK自带的keytool工具来创建自签发的证书,并保存到密钥库文件中。如果要把一个密钥库导入到另一个密钥库(比如到另一台机器上安装,同时又不想用覆盖文件的方式),那该怎么操作呢?

比如,我们从aaa.jks里把别名为tomcat的内容导入到bbb.jks里。一个错觉是先从aaa.jks导出证书、再导入到bbb.jks里。

为说明错误情况,我们从头做起。先生成别名为tomcat的证书,并保存到aaa.jks里:

keytool -keystore aaa.jks -genkey -keyalg RSA -alias tomcat

然后把证书导出到tomcat.cert文件:

keytool -keystore aaa.jks -export -file tomcat.cert -alias tomcat

接着把tomcat.cert导入到bbb.jks里:

keytool -keystore bbb.jks -import -file tomcat.cert -alias tomcat

 

为验证这种做法的错误性,我们可分别用aaa.jks和bbb.jks来启动Tomcat服务器,看看能不能启动成功。由于我们仅仅是出于验证的目的,因此无需在Tomcat的webapps目录里放进应用的war包文件。

先用aaa.jks来启动Tomcat。修改Tomcat的conf\server.xml文件为:

    <Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol" SSLEnabled="true"
               maxThreads="150" scheme="https" secure="true"
               clientAuth="false" sslProtocol="TLS"
               keystoreFile="aaa.jks"
               keystorePass="changeit" />

请把上面的aaa.jks输入为实际的全路径名(比如d:\aaa.jks)。完成后启动Tomcat,此时Tomcat应能够成功启动。

确认成功后请关闭Tomcat,接下来我们把上面的aaa.jks换为bbb.jks,保存后重新启动Tomcat。Tomcat将报异常:

严重: Failed to initialize connector [Connector[HTTP/1.1-8443]]
org.apache.catalina.LifecycleException: Failed to initialize component [Connector[HTTP/1.1-8443]]
        at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:106)
        at org.apache.catalina.core.StandardService.initInternal(StandardService.java:559)
        at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
        at org.apache.catalina.core.StandardServer.initInternal(StandardServer.java:814)
        at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
        at org.apache.catalina.startup.Catalina.load(Catalina.java:633)
        at org.apache.catalina.startup.Catalina.load(Catalina.java:658)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:281)
        at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:450)
Caused by: org.apache.catalina.LifecycleException: Protocol handler initialization failed
        at org.apache.catalina.connector.Connector.initInternal(Connector.java:983)
        at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
        ... 12 more
Caused by: java.io.IOException: Alias name tomcat does not identify a key entry
        at org.apache.tomcat.util.net.jsse.JSSESocketFactory.getKeyManagers(JSSESocketFactory.java:567)
        at org.apache.tomcat.util.net.jsse.JSSESocketFactory.getKeyManagers(JSSESocketFactory.java:505)
        at org.apache.tomcat.util.net.jsse.JSSESocketFactory.init(JSSESocketFactory.java:449)
        at org.apache.tomcat.util.net.jsse.JSSESocketFactory.createSocket(JSSESocketFactory.java:158)
        at org.apache.tomcat.util.net.JIoEndpoint.bind(JIoEndpoint.java:393)
        at org.apache.tomcat.util.net.AbstractEndpoint.init(AbstractEndpoint.java:610)
        at org.apache.coyote.AbstractProtocol.init(AbstractProtocol.java:429)
        at org.apache.coyote.http11.AbstractHttp11JsseProtocol.init(AbstractHttp11JsseProtocol.java:119)
        at org.apache.catalina.connector.Connector.initInternal(Connector.java:981)
        ... 13 more

为什么用bbb.jks启动不了呢?为此我们分别检查一下aaa.jks和bbb.jks里的内容。

下面是aaa.jks里的内容:

keytool -keystore aaa.jks -list -alias tomcat
输入keystore密码:
tomcat, 2012-12-2, PrivateKeyEntry,
认证指纹 (MD5): 20:E1:74:4B:0B:35:33:FF:BE:2D:9D:B5:31:AB:3B:DE

 下面是bbb.jks里的内容:

keytool -keystore bbb.jks -list -alias tomcat
输入keystore密码:
tomcat, 2012-12-2, trustedCertEntry,
认证指纹 (MD5): 20:E1:74:4B:0B:35:33:FF:BE:2D:9D:B5:31:AB:3B:DE

从上面两个输出中可见其差别,一个是PrivateKeyEntry,另一个是trustedCertEntry。

其实,密钥库里保存了两类信息,一类是私钥,另一类是证书。证书里只有公钥。上面导出的tomcat.cert文件为证书文件,里面没有私钥。因此当我们再导入到bbb.jks时,导进去的只有证书、没有对应的私钥。而服务器需要用私钥与客户端的公钥通讯,因此Tomcat报了上面的异常。

 

那么我们该如何正确操作呢?方法有很多,最常用的方法是不用keytool来生成证书和私钥,而改用openssl工具。不过本文的目的是只用keytool来操作。

其实操作很简单:

keytool -importkeystore -deststorepass changeit -destkeypass changeit -destkeystore bbb.jks -deststoretype jks -srckeystore aaa.jks -srcstoretype jks -srcstorepass changeit -alias tomcat

这个bbb.jks就包含了别名为tomcat的私钥和证书了。如果不放心可再用启动Tomcat的方法去验证一下。

最后要说明的是,如果在keytool中不指定storetype、srcstoretype、deststoretype参数则也默认为jks。

posted @ 2012-12-02 15:57  yang wu  阅读(11055)  评论(0编辑  收藏  举报