Java UnrecoverableKeyException:无法恢复密钥
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25488203/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
UnrecoverableKeyException: Cannot recover key
提问by PAN
I have an application where the server side code loads the keystore -
我有一个服务器端代码加载密钥库的应用程序 -
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream(keyStoreFile), "password".toCharArray());
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, "privatepassword".toCharArray());
SSLContext sslCtx = SSLContext.getInstance("TLS");
sslCtx.init(kmf.getKeyManagers(), null, null);
This worked fine when I had only one private key in the keystore. When I added another private key (with a different password) to the keystore I got this error
当我在密钥库中只有一个私钥时,这很好用。当我向密钥库添加另一个私钥(使用不同的密码)时,出现此错误
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)
I then tried creating a custom keymanager as specified in the link below
然后我尝试创建一个自定义的密钥管理器,如下面的链接中指定的
@Bruno I tried the suggestion you have given. However that does not work. My custom key manager factory looks like this -
@Bruno 我尝试了您给出的建议。但是,这不起作用。我的自定义密钥管理器工厂看起来像这样 -
class CustomKeyManager implements X509KeyManager {
private final KeyStore ks;
private final String alias;
public CustomKeyManager(KeyStore ks, String alias) {
this.ks = ks;
this.alias = alias;
}
@Override
public String[] getClientAliases(String paramString,
Principal[] paramArrayOfPrincipal) {
return new String[]{alias};
}
@Override
public String chooseClientAlias(String[] paramArrayOfString,
Principal[] paramArrayOfPrincipal, Socket paramSocket) {
// TODO Auto-generated method stub
return alias;
}
@Override
public String[] getServerAliases(String paramString,
Principal[] paramArrayOfPrincipal) {
// TODO Auto-generated method stub
return new String[] {alias};
}
@Override
public String chooseServerAlias(String paramString,
Principal[] paramArrayOfPrincipal, Socket paramSocket) {
// TODO Auto-generated method stub
return alias;
}
@Override
public X509Certificate[] getCertificateChain(String paramString) {
// TODO Auto-generated method stub
return null;
}
@Override
public PrivateKey getPrivateKey(String paramString) {
PrivateKey pk = null;
try { //have hardcoded this to the key i am working with
pk = (PrivateKey) ks.getKey("mykey", "privatepassword".toCharArray());
} catch (UnrecoverableKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (KeyStoreException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return pk;
}
}
}
After I create an object of CustomKeyManager if I make a call to getPrivateKey I get a non null private key -
在创建 CustomKeyManager 对象后,如果我调用 getPrivateKey,我会得到一个非空私钥 -
Sun RSA private CRT key, 1024 bits modulus: 117260821110864021601500037071432398877761428124640545232618906306796101075244931231861318133902594657774603548686479580347869030216483422242066483203953111970007516384847036243243010603169399491545560497255823475630452314709747201644535089867367118834303975042348737995500693672037616900410158764770570813729 .......
孙RSA私人CRT键,1024位模数:117260821110864021601500037071432398877761428124640545232618906306796101075244931231861318133902594657774603548686479580347869030216483422242066483203953111970007516384847036243243010603169399491545560497255823475630452314709747201644535089867367118834303975042348737995500693672037616900410158764770570813729 .......
This tells me that my getPrivateKey is working.
这告诉我我的 getPrivateKey 正在工作。
I use the CustomKeyManager in the following manner
我按以下方式使用 CustomKeyManager
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream(keyStoreFile), "password".toCharArray());
SSLContext sslCtx = SSLContext.getInstance("TLS");
CustomKeyManager ck = new CustomKeyManager(ks, "mykey");
KeyManager[] kms = new KeyManager[1];
kms[0] = ck;
System.out.println(ck.getPrivateKey("mykey")); //returns a non null value
sslCtx.init(kms , null, null); //throws an exception
The exception I get is
我得到的例外是
javax.net.ssl.SSLHandshakeException: no cipher suites in common
javax.net.ssl.SSLHandshakeException:没有共同的密码套件
Is there a mistake in the way I am creating and using the CustomKeyManager. The other thing of interest is that if I set breakpoints to all the method entry points in the CustomKeyManager, none of them are hit.
我创建和使用 CustomKeyManager 的方式是否有错误?另一件有趣的事情是,如果我为 CustomKeyManager 中的所有方法入口点设置断点,则不会命中它们。
采纳答案by Bruno
Your UnrecoverableKeyException
happens because the keymanager isn't using the correct password. As you said, your two private keys use different passwords.
The code you link to isn't going to help here, since it's merely wrapping the behaviour of the existing keymanager, which you've initialised with only one of the two passwords.
您UnrecoverableKeyException
之所以会发生这种情况,是因为密钥管理器没有使用正确的密码。正如您所说,您的两个私钥使用不同的密码。您链接到的代码在这里无济于事,因为它只是包装了现有密钥管理器的行为,您仅使用两个密码之一对其进行了初始化。
If you really want to use two distinct passwords, you'll need to implement getPrivateKey(String alias)
in your custom X509KeyManager
to take this into account. In particular, it will have to load the keys from your KeyStore
instance with the right password for each alias (see getKey(String alias, char[] password)
).
如果您真的想使用两个不同的密码,则需要getPrivateKey(String alias)
在自定义中实施以将X509KeyManager
其考虑在内。特别是,它必须KeyStore
使用每个别名的正确密码从您的实例加载密钥(请参阅 参考资料getKey(String alias, char[] password)
)。