我如何 encrypt/decrypt 通过使用 Bouncy Castle Java 库和 JKS 中持久保存的证书来满足 ELGAMAL PGP 算法

How can I encrypt/decrypt content with ELGAMAL PGP algorithm by using Bouncy Castle Java library with Certificates persisted in JKS

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

然而,当我尝试使用“JcaPGPKeyConverter”并且如果我为 public 密钥类型提供“PublicKeyAlgorithmTags.ELGAMAL_GENERAL”时,我会得到“org.bouncycastle.openpgp.PGPException:未知 EC 算法”异常。

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

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 并且只使用写在 Public Key 对象上的算法,我想我不再使用 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 读取的证书转换为 PGPPublic密钥? 或者我可以直接在 PGPEncryptedDataGenerator 上定义加密算法 (ELGAMAL) 吗?

感谢您的帮助..

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

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