在 Java 中,如何使用来自 JKS 密钥库内的 X509 证书(公钥/私钥对)的私钥进行解密?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/34227317/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 22:37:36  来源:igfitidea点击:

In Java, how do I decrypt using the private key from an X509 certificate (public/private key pair) inside a JKS keystore?

javaencryptionrsajks

提问by Brian T Hannan

I created a KeyStoreusing KeyStore Explorer with a public/private key pairinside it of type RSA, 4096 bytes, and PKCS#8 formatting.

我使用 KeyStore Explorer创建了一个KeyStore,里面有一个公钥/私钥对,类型为RSA、4096 字节和 PKCS#8 格式

I get an errorwhen my code runs and hits the cipher.init()method :

当我的代码运行并命中cipher.init()方法时出现错误

"Key for algorithm RSA not suitable for symmetric encryption."

“算法 RSA 的密钥不适合对称加密。”

This doesn't really make sense to me because I'm using asymmetric key encryption/decryption. I'm not sure where to go from here or what I'm doing wrong.

这对我来说没有意义,因为我使用的是非对称密钥加密/解密。我不知道从哪里开始或我做错了什么。

Here is what I have:

这是我所拥有的:

public TransactionData processData(TransactionData data) throws BTHException {
    String keystoreFilePath = manager.getStringValue(KeyStoreFilePath);
    String keystorePassword = manager.getStringValue(KeyStoreFilePassword);
    String privateKeyPassword = manager.getStringValue(KeyStorePrivateKeyPassword);
    String certificateAlias = manager.getStringValue(CertificateAlias);

    org.apache.xml.security.Init.init();

    try {
        InputStream in = data.getDataStream();
        byte[] dataBytes = DataUtil.readBytes(in);
        String encryptedDataStr = new String(dataBytes);

        PrivateKey privateKey = getPrivateKeyFromKeyStore(keystoreFilePath, keystorePassword, certificateAlias, privateKeyPassword);

        decrypt(
            encryptedDataStr,
            privateKey
        );
    }catch(Exception e){
        throw new BTHException(e.getMessage());
    }

    return data;
}

private PrivateKey getPrivateKeyFromKeyStore(String keyStoreFilePath, String keyStorePassword, String privateKeyCertAlias, String privateKeyPassword) throws BTHException {
    PrivateKey privateKey = null;
    try {
        KeyStore keystore = KeyStore.getInstance("JKS");
        BASE64Encoder encoder = new BASE64Encoder();
        keystore.load(new FileInputStream(keyStoreFilePath), keyStorePassword.toCharArray());
        Key key=keystore.getKey(privateKeyCertAlias,keyStorePassword.toCharArray());
        if(key instanceof PrivateKey) {
            Certificate cert=keystore.getCertificate(privateKeyCertAlias);
            PublicKey publicKey=cert.getPublicKey();
            KeyPair keyPair = new KeyPair(publicKey,(PrivateKey)key);
            privateKey = keyPair.getPrivate();
        }
        //privateKeyEncoded = encoder.encode(privateKey.getEncoded());
    } catch (Exception e) {
        throw new BTHException(e.getMessage());
    }
    return privateKey;
}

private String decrypt(String cipherText, PrivateKey privateKey) throws IOException, GeneralSecurityException, BTHException {
    String decryptedValue = null;

    try {
        // 1. Get the cipher ready to start doing the AES transformation
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

        // 2. Start the decryption process
        // THIS IS WHERE IT FAILS
        cipher.init(Cipher.DECRYPT_MODE, privateKey);

        // 3. Finish the decryption process
        decryptedValue = new String(cipher.doFinal(Base64.decodeBase64(cipherText)), "UTF-8");
    } catch (Exception e) {
        throw new BTHException(e.getMessage());
    }

    return decryptedValue;
}

Any help would be great. Thanks in advance!

任何帮助都会很棒。提前致谢!

采纳答案by Dennis Kriechel

You are trying to initialize your cipher as AES/CBC/PKCS5Paddingwhich is an symmetric encryptionand that is where the exception originates.

您正在尝试初始化密码为AES/CBC/PKCS5Padding这是一种对称加密,这是异常源自哪里。

You should use the Cipherlike that:

你应该使用Cipher这样的:

// 1. Get the cipher ready to start doing the RSA transformation
Cipher cipher = Cipher.getInstance("RSA");

// 2. Start the decryption process
cipher.init(Cipher.DECRYPT_MODE, privateKey);

Here you can find a good example for RSA-Encryption and Decryption.

在这里您可以找到RSA-Encryption 和 Decryption 的一个很好的例子。