为什么在Java中创建SSL套接字时出现错误“无法存储非私有密钥”?


问题内容

我正在使用旧版本的IBM iSeries(IBM-i,i5OS,AS / 400等),并在O / S版本V5R3M0上使用Java 5
JVM(经典,而不是ITJ J9)。

简而言之,这是场景:

  1. 我使用Portecle 1.7创建了类型为JKS的密钥库(注意:我确实尝试将密钥库转换为JCEKS,但由于不支持的格式而被拒绝,因此JKS是iSeries机器的唯一选择(至少我使用的版本)。
  2. 然后,我创建了密钥对和CSR,并将CSR发送给Thawte进行签名。
  3. 我成功地使用PKCS#7格式从Thawte导入了签名证书,以导入整个证书链,其中包括我的证书,Thawte中介和Thawte服务器根目录。

这一切都按预期进行。

但是,当我运行JVM时,将其正确配置为指向商店并提供它的密码(我过去使用在Portecle中创建的用于测试的自签名证书来完成此操作),然后尝试在443上启动Web服务器,我收到以下安全异常:

java.security.KeyStoreException: Cannot store non-PrivateKeys

谁能告诉我我哪里出了问题,或者接下来我要检查什么?


问题答案:

无需使用临时密钥库,您可以在单个中处理所有内容SSLContext

您需要SSLContext使用自定义来初始化您的自定义设置,X509KeyManager而不是使用default给出的自定义设置KeyManagerFactory。在此X509KeyManagerchooseServerAlias(String keyType, Principal[] issuers, Socket socket)应根据从套接字获得的本地地址返回不同的别名。

这样,您就不必担心将私钥从一个密钥库复制到另一个,这甚至适用于不能从中提取(并因此复制)但仅使用私钥的密钥库类型,例如PKCS #11。