如何使用带有 JKS 中持久化证书的 Bouncy Castle Java 库使用 ELGAMAL PGP 算法加密/解密内容

问题描述

我需要使用 PGP 和 ELGAMAL 算法加密和解密一些消息。我的密钥存储在 JKS 密钥库中。据我所知,我首先需要从 JKS 读取密钥/证书并将它们转换为 PGP 密钥,以便它们可以在 PGP 加密器中使用。

但是,当我尝试使用“JcaPGPKeyConverter”并且如果我为公钥类型提供“PublicKeyAlgorithmTags.ELGAMAL_GENERAL”时,我会得到“org.bouncycastle.openpgp.PGPException:unknown EC algorithm”异常。

这是生成 PGP 公钥的转换器代码:

JcaPGPKeyConverter jcaPGPKeyConverter = new JcaPGPKeyConverter();
Certificate encryptionCertificate = keyStore.getCertificate(certificateAlias);
PGPPublicKey pgpEncryptionPublicKey = jcaPGPKeyConverter.getPGPPublicKey(
             PublicKeyAlgorithmTags.ELGAMAL_GENERAL,// if I use ECDH here converter works
             encryptionCertificate.getPublicKey(),new Date());

这是堆栈跟踪:

org.bouncycastle.openpgp.PGPException: unknown EC algorithm
    at org.bouncycastle.openpgp.operator.jcajce.JcaPGPKeyConverter.getPublicBCPGKey(Unknown Source)
    at org.bouncycastle.openpgp.operator.jcajce.JcaPGPKeyConverter.getPGPPublicKey(Unknown Source)
    at org.bouncycastle.openpgp.operator.jcajce.JcaPGPKeyConverter.getPGPPublicKey(Unknown Source)

它适用于“PublicKeyAlgorithmTags.ECDH”(我在 JcaPGPKeyConverter 的源代码中找到),但在后面的步骤中,我从生成的 PGPPublicKey 中获得了加密方法。因此,如果我在转换器上使用 ECDH 并且只使用写在公钥对象上的算法,那么我想我就不再使用 ELGAMAL 进行加密了:

PGPEncryptedDataGenerator encryptedDataGenerator = new PGPEncryptedDataGenerator(
new JcePGPDataEncryptorBuilder(SymmetricKeyAlgorithmTags.AES_256) //
                    .setWithIntegrityPacket(true) //
                    .setSecureRandom(random) //
                    .setProvider(BOUNCY_CASTLE));
// Here I use previously converted public key to generate encryption method and it gets algorithm from public key:
JcePublicKeyKeyEncryptionMethodGenerator encryptionMethodGenerator = 
                                         new JcePublicKeyKeyEncryptionMethodGenerator(pgpEncryptionPublicKey)
                                        .setProvider(BOUNCY_CASTLE);
encryptedDataGenerator.addMethod(encryptionMethodGenerator);

我在 Internet 上看到过使用 ELGAMAL 的示例,但所有示例都是即时生成密钥的。 我需要使用 JKS/JCEKS 中持久化的密钥。

还有其他方法可以将从 JKS 读取的证书转换为 PGPPublicKey 吗? 或者我可以直接在 PGPEncryptedDataGenerator 上定义加密算法(ELGAMAL)吗?

感谢您的帮助..

解决方法

似乎“jcaPGPKeyConverter.getPGPPublicKey”需要证书的创建日期。在上面的第一个代码块中,我使用执行时间作为带有 'new Date()' 参数的创建时间。

如果加密和解密在同一分钟内发生,例如在单元测试中,这会起作用。否则,由于我们使用不同的时间参数转换密钥,因此在不同时间转换的密钥无法按预期工作。用证书创建时间替换 'new Date()' 参数解决了这个问题。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...