java.lang.Exception: Public 回复和密钥库中的密钥不匹配

java.lang.Exception: Public keys in reply and keystore don't match

我必须访问托管在 443.Service 端口的 Web 服务,提供商已与我们共享三个证书。

  1. ABCD.cer
  2. CA_Certificate.cer
  3. CCA_Certificate.cer

我必须通过为 SSL 创建表单链将它们添加到密钥库 communication.I 已执行以下步骤。

  1. keytool -keystore npci_keystore_test.jks -genkey -alias npci_client_testore

       Result :- keystore npci_keystore_test.jks created.
    
  2. keytool -import -keystore npci_keystore_test.jks -file CA_Certificate.cer -alias theCARoot

       Result :- certificate CA_Certificate.cer is added to keystore.
    
  3. keytool -import -keystore npci_keystore_test.jks -file CCA_Certificate.cer -alias theCCARoot

       Result :- certificate CCA_Certificate.cer is added to keystore.
    
  4. keytool -import -keystore npci_keystore_test.jks -file ABCD.cer -alias npci_client_testore

    在第 4 步我有以下异常

    输入密钥库密码:(当我输入密码时出现以下异常)

    keytool 错误:java.lang.Exception:Public 回复中的密钥和密钥库不匹配

我已经在 SO 中进行了搜索,但到目前为止还没有成功。

我正在按照以下来源创建商店并在其中导入证书。 JKS Keystore

编辑:---

我已经通过更改证书的导入顺序进行了测试,但到目前为止没有成功。

您问题中的 link 解释了如何为服务器创建 SSL 密钥库,这不是您想要做的。您所做的是:

  1. 创建新的密钥对
  2. 将受信任的证书添加到密钥库
  3. 将另一个受信任的证书添加到密钥库
  4. 尝试导入服务器的 SSL 证书作为您的密钥对的证书

第 4 步失败,因为 SSL 证书是为完全不同的密钥对生成的。

三个证书大概是:

  1. 网络服务的SSL证书
  2. 签署 SSL 证书的 CA 证书
  3. 签署 CA 的根证书

您现在要做的是将信任锚添加到您的信任库(默认情况下:${JAVA_HOME}/jre/lib/security/cacerts),结果是您的客户端接受 Web 服务的 SSL 证书。

通常SSL服务器在SSL握手期间将除根证书之外的整个链发送给客户端。这意味着您必须将根证书添加到您的信任库:

keytool -import -keystore ${JAVA_HOME}/jre/lib/security/cacerts -file CCA_Certificate.cer -alias theCCARoot

如果 web 服务需要 SSL 客户端身份验证,则需要额外的步骤,但您从未提到过客户端身份验证,因此我认为没有必要。

这里的问题是您在导入证书时使用的别名与您在创建 JKS 商店时使用的别名相似。只需更改别名即可解决您的问题。源文档[1]需要相应修改。

[1] http://docs.oracle.com/cd/E19509-01/820-3503/ggfgo/index.html

在我的例子中,链中缺少 "The root certificate that signed the CA"。请检查您是否有适当的 ROOT CA 证书,否则将其从中间导出并导入到密钥库中。将根 CA 导入我的密钥库对我有用。

在第 4 点(出现错误:keytool 错误:java.lang.Exception:Public 回复和密钥库中的密钥不匹配)在您导入证书的地方,请更改别名。别名不应为 npci_client_testore,因为它已被用作密钥库的别名。

这对我有用:

keytool -keystore yourkeystorename -importcert -alias certificatealiasname -file certificatename.cer

我在托管 Tomcat8 时遇到了相同的异常错误(密钥库不匹配)。如果您在创建密钥库时输入了 wrong domain nameno domain name,您将需要再次重新创建密钥库文件并再次将您的 CSR 重新提交给您的证书颁发机构 (CA) licensed/recognised/approved 以颁发数字签名证书(在我的例子中是 Godaddy)。

以下是创建密钥库文件的命令:

keytool -keysize 2048 -genkey -alias tomcat -keyalg RSA -keystore tomcat.keystore
keytool -importkeystore -srckeystore tomcat.keystore -destkeystore tomcat.keystore -deststoretype pkcs12

(当提示要求名字和姓氏时,您需要输入域名,它要求完全合格的域名 (FDQN) 例如 www.example.com)。来自城市、州和省 - do not abbreviate

输入以下命令创建 CSR(从与您的 tomcat.keystore 位置相同的目录):

keytool -certreq -keyalg RSA -alias tomcat -file myFQDN.csr -keystore tomcat.keystore

注意:由于之前的“密钥库不匹配”错误,我不得不从 windows 控制台 (MMC) 中删除所有 Godaddy 证书。

一旦您的证书颁发机构准备好您的证书文件。下载文件并双击 2 个 .crt 文件中的每一个以在 windows 中再次重新安装它们(选择自动安装在本地计算机中)。确保备份 tomcat.keystore 文件,然后 按顺序 将这些证书文件导入 tomcat.keystore 文件(从头开始),顺序与以下示例相同:

keytool -import -alias root -keystore tomcat.keystore -trustcacerts -file gdig2.crt.pem
keytool -import -alias intermed -keystore tomcat.keystore -trustcacerts -file gd_bundle-g2-g1.crt
keytool -import -alias tomcat -keystore tomcat.keystore -trustcacerts -file namewithnumbersandletters.crt

确保您已更新 server.xml 然后重新启动 Tomcat

<Connector port="80" protocol="HTTP/1.1"
    relaxedQueryChars="|{}[]%-"
    connectionTimeout="20000"
    redirectPort="443" />  
<Connector  SSLEnabled="true" URIEncoding="UTF-8" 
    clientAuth="false" 
    keystoreFile="C:\Program Files\Java\jdk-11.0.9\bin\tomcat.keystore" 
    keystorePass="ChangeToYourPassword" 
    maxThreads="200" 
    port="443" 
    scheme="https" 
    secure="true" 
    sslProtocol="TLS"
    sslEnabledProtocols="TLSv1.2"
    ciphers="TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
    TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
    TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
    TLS_RSA_WITH_AES_256_CBC_SHA256, TLS_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
    TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384" /> 

瞧!在域上浏览时会出现锁定图标(安全连接)。

与@Omikron 的回答类似,我通过将 TrustedRoot.crtDigiCertCA.crt 文件添加到 jre/lib/security/cacerts 密钥库来解决它。

sudo keytool -import -alias ALIAS -file TrustedRoot.crt -storetype JKS -keystore ${JAVA_HOME}/jre/lib/security/cacerts -file DigiCertCA.crt

然后我能够将证书导入我自己的密钥库。

keytool -import -trustcacerts -alias other_alias -file certificate.crt -keystore keystore.jks -keypass "password" -storepass "password1"

当您尝试将证书导入现有的 jks 文件时会发生这种情况,该文件中已经存在相同的别名。如果您想使用相同的别名,请先删除旧别名及其在 jks 中的关联证书,然后再导入新别名。

1 - keytool -delete -alias <alias_name> -keystore <your jks file name>
2 - keytool -import -alias <alias_name> -keystore <your jks file name> -file <your source cer or crt file>