由:java.security.UnrecoverableKeyException引起:无法恢复密钥

103

我有一个名为ABCC_client.store的jks密钥库。当我将此密钥库导入cacerts并尝试连接时,会出现“没有这样的算法”错误。请参见堆栈跟踪信息。

    Caused by: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class:   com.sun.net.ssl.internal.ssl.DefaultSSLContextImpl)
    at java.security.Provider$Service.newInstance(Provider.java:1245)
    at sun.security.jca.GetInstance.getInstance(GetInstance.java:220)
    at sun.security.jca.GetInstance.getInstance(GetInstance.java:147)
    at javax.net.ssl.SSLContext.getInstance(SSLContext.java:125)
    at javax.net.ssl.SSLContext.getDefault(SSLContext.java:68)
    at javax.net.ssl.SSLSocketFactory.getDefault(SSLSocketFactory.java:102)
    at org.apache.axis.components.net.JSSESocketFactory.initFactory(JSSESocketFactory.java:61)
    at org.apache.axis.components.net.JSSESocketFactory.create(JSSESocketFactory.java:79)
    ... 32 more
Caused by: java.security.UnrecoverableKeyException: Cannot recover key
    at sun.security.provider.KeyProtector.recover(KeyProtector.java:311)
    at sun.security.provider.JavaKeyStore.engineGetKey(JavaKeyStore.java:121)
    at sun.security.provider.JavaKeyStore$JKS.engineGetKey(JavaKeyStore.java:38)
    at java.security.KeyStore.getKey(KeyStore.java:763)
    at com.sun.net.ssl.internal.ssl.SunX509KeyManagerImpl.<init>(SunX509KeyManagerImpl.java:113)
    at com.sun.net.ssl.internal.ssl.KeyManagerFactoryImpl$SunX509.engineInit(KeyManagerFactoryImpl.java:48)
    at javax.net.ssl.KeyManagerFactory.init(KeyManagerFactory.java:239)
    at com.sun.net.ssl.internal.ssl.DefaultSSLContextImpl.getDefaultKeyManager(DefaultSSLContextImpl.java:170)
    at com.sun.net.ssl.internal.ssl.DefaultSSLContextImpl.<init>(DefaultSSLContextImpl.java:40)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    at java.lang.Class.newInstance0(Class.java:355)
    at java.lang.Class.newInstance(Class.java:308)
    at java.security.Provider$Service.newInstance(Provider.java:1221)
    ... 39 more

但是,如果我独立使用此密钥库,即不将其添加到cacerts中,则可以正常工作。

一些搜索结果指向了我这个网站:http://joewlarson.com/blog/2009/03/25/java-ssl-use-the-same-password-for-keystore-and-key/,其中提到密钥和密钥库的密码可能不同。


有没有一点代码可以查看正在调用什么? - Bruno
我正在尝试从代码中调用Web服务方法...AxisFault故障代码:{http://schemas.xmlsoap.org/soap/envelope/}Server.userException故障子代码:错误字符串:java.net.SocketException:java.security.NoSuchAlgorithmException:构建实现时出错(算法:Default,提供程序:SunJSSE,类:com.sun.net.ssl.internal.ssl.DefaultSSLContextImpl) - Mrinal Bhattacharjee
2
这里可能重复了一个类似的问题(https://dev59.com/A3M_5IYBdhLWcg3wlEFH),并且有一个答案。 - icrovett
我的问题是,如果我们设置系统属性使用密钥库,则密钥库可以正常工作。但是,如果我们将该密钥库加载到JVM的默认位置即cacerts中,则无法正常工作。它会显示证书错误。 - Mrinal Bhattacharjee
在我的情况下,我被提供了错误的密码。 - nikhil2000
6个回答

136
如果使用Tomcat 6或更早版本,请确保密钥库密码和密钥密码相同。如果使用Tomcat 7或更高版本,请确保它们相同,或者在server.xml文件中指定密钥密码。

10
这是真的。参考 https://tomcat.apache.org/tomcat-6.0-doc/ssl-howto.html#Prepare_the_Certificate_Keystore - Atharva
2
相关引用:最后,您将被提示输入“密钥密码”,这是专门为此证书设置的密码(而不是存储在同一密钥库文件中的任何其他证书的密码)。您必须在此处使用与密钥库密码相同的密码。这是Tomcat实现的限制。(目前,“keytool”提示将告诉您按ENTER键会自动执行此操作。) - Captain Man
我在使用JMeter(https)时遇到了问题,因为Java密钥库和密钥密码不同。参考 https://dev59.com/WnE85IYBdhLWcg3wNgvk?noredirect=1&lq=1 ,更改密钥密码以解决问题。非常有帮助!谢谢。 - Rishi
@CaptainMan 这只适用于Tomcat6,在Tomcat7中不再适用(https://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Prepare_the_Certificate_Keystore)。 - Andrea Ligios
2
@AndreaLigios 好观点,相关引用:最后,您将被提示输入密钥密码,这是专门为此证书设置的密码(而不是存储在同一密钥库文件中的任何其他证书的密码)。keytool提示将告诉您,按ENTER键会自动使用与密钥库相同的密码。您可以自由选择使用相同的密码或选择自定义密码。如果您选择与密钥库密码不同的密码,则还需要在server.xml配置文件中指定自定义密码。 - Captain Man
显示剩余2条评论

81

您在app/config中定义的私钥密码不正确。首先,请尝试通过以下方式更改为另一个私钥密码来验证私钥密码:

keytool -keypasswd -new changeit -keystore cacerts -storepass changeit -alias someapp -keypass password

上面的例子将密码从 "password" 更改为 "changeit"。如果私钥密码是 "password",则此命令将成功。


3
虽然我没有将这个答案与问题联系起来,但它对于验证密钥库文件、存储密码、别名/密钥和密钥密码非常有帮助。 - Russ
1
请记住,在执行此命令后,您将更改密钥库密码。您需要将密码设置回原始密码。 - gersonZaragocin
实际上,只需要指定-keypasswd -keystore storefile -alias somealias并在提示中输入其他所有内容即可。 - Andrey Regentov
1
运行此代码时,我遇到了以下错误 - "keytool error: java.security.UnrecoverableKeyException: Cannot recover key" 有没有办法检查我的别名密钥密码或在不知道旧密码的情况下更改它? - Kavin Raju S

10
为了避免出现“无法恢复密钥”异常,我必须将Java加密扩展(JCE)无限制权限策略文件应用于运行我的应用程序的Java安装。这些文件的第8版可以在此处找到,或者最新版本应该列在此页面上。下载包括一个文件,说明如何应用策略文件。
JDK 8u151 开始,不再需要添加策略文件。相反,JCE管辖范围的策略文件由一个名为crypto.policy的安全属性控制。将其设置为unlimited将允许JDK使用无限制的加密。如上面链接的发布说明所述,它可以通过Security.setProperty()或通过java.security文件进行设置。还可以通过在启动程序时添加-Djava.security.properties=my_security.properties来附加java.security文件,详见此处
JDK 8u161以来,无限制加密已默认启用。

3
尽管安装了策略文件的JAR包,我仍然看到这个错误。 - Adam
@Adam 我的解决方案是针对特定情况的,可能与你遇到的不同。但是我已经添加了一个更新来反映在JDK 8u151中发生的更改。 - WhiteKnight

6

运行以下命令检查您使用的密码是否正确:

keytool -keypasswd -new temp123 -keystore awsdemo-keystore.jks -storepass temp123 -alias movie-service -keypass changeit

如果您收到以下错误信息,则表示密码错误:
keytool error: java.security.UnrecoverableKeyException: Cannot recover key

7
如果我使用其他密码,我会收到错误信息“密钥库被篡改或密码不正确”。如果我使用我知道是正确的密码,我会收到错误消息“无法恢复密钥”。因此,我不认为你的说法是正确的,至少在我的情况下。可能还有其他原因导致这个错误。 - Alexandru Severin
当keyAlias参数缺失或值与密钥库中的别名名称不匹配时,Tomcat可能会引起此问题。通过发出keytool -list -keystore something.jks -storepass temp123命令并检查列表中的别名来确保您正在使用正确的别名。 - Gabor Garami

5

当我们将一个使用64位OpenSSL版本构建的密钥导入到keystore时,我遇到了相同的错误。当我们按照相同的步骤将密钥导入到使用32位OpenSSL版本构建的keystore中时,一切都很顺利。


4
上述错误的根本原因是java.security.UnrecoverableKeyException:无法恢复密钥。如上所述,这可能是由于密码错误,也可能是由于使用64位OpenSSL实现构建的密钥库。因此,我认为我的答案是另一种可能的解决方案。它在同样的错误情况下对我有帮助,因此我在这里提供了解决方案。 - Heimi
OpenSSL不会创建Java密钥库文件。您能否澄清一下这个问题? - aled
谢谢您的回答。在调用OpenESB 3.05中的https Web服务时,我也遇到了同样的问题。我按照您的指示使用32位OpenSS实现重新生成了jks文件,目前已经解决了这个问题。 - Marti Pàmies Solà

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接