java - 无法恢复的 key 异常 : Cannot recover key

标签 java ssl ssl-certificate

<分区>

我有一个服务器端代码加载 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);

当我在 keystore 中只有一个私钥时,这工作得很好。当我向 keystore 添加另一个私钥(使用不同的密码)时,出现此错误

    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)

然后我尝试按照下面的链接创建自定义 key 管理器

@布鲁诺 我尝试了你给出的建议。但是,这不起作用。我的自定义 key 管理器工厂看起来像这样 -

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;
}   

在我创建 CustomKeyManager 对象后,如果我调用 getPrivateKey,我会得到一个非空私钥 -

Sun RSA CRT 私钥,1024 位 modulus: 117260821110864021601500037071432398877761428124640545232618906306796101075244931231861318133902594657774603548686479580347869030216483422242066483203953111970007516384847036243243010603169399491545560497255823475630452314709747201644535089867367118834303975042348737995500693672037616900410158764770570813729 …………

这告诉我我的 getPrivateKey 正在工作。

我按以下方式使用 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

我得到的异常是

javax.net.ssl.SSLHandshakeException:没有共同的密码套件

我创建和使用 CustomKeyManager 的方式是否有错误。另一件有趣的事情是,如果我为 CustomKeyManager 中的所有方法入口点设置断点,它们都不会被命中。

最佳答案

您的 UnrecoverableKeyException 发生是因为 key 管理器没有使用正确的密码。如您所说,您的两个私钥使用不同的密码。 您链接到的代码在这里没有帮助,因为它只是包装了现有 key 管理器的行为,您只使用两个密码之一对其进行了初始化。

如果您真的想使用两个不同的密码,您需要在您的自定义 X509KeyManager 中实现 getPrivateKey(String alias) 以考虑到这一点。特别是,它将必须使用每个别名的正确密码从您的 KeyStore 实例加载 key (参见 getKey(String alias, char[] password) )。

关于java - 无法恢复的 key 异常 : Cannot recover key,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25488203/

相关文章:

java - 远程访问hbase

java - 必需的字符串参数 'email' 不存在

c++ - Qt中如何实现OpenSSL?

java - 忽略证书时出现 CertificateException

ssl - 在 Nginx 上禁用 SSLv3

java - 有什么方法可以重用 Stream 吗?

java - Window.open 不适用于 IE7

android - 您在哪里可以找到 Android 中信任管理器的默认实现?

ssl - 我应该为 ssl 证书的私钥使用哪种加密 AES/DES?

linux - 如何在 Linux 上使用 Go 指定自定义 SSL 根目录