如何使用 BouncyCastle 使用 AES-GCM 加密 CMS EnvelopedData 值?

How to encrypt a CMS EnvelopedData value with AES-GCM using BouncyCastle?

我可以使用以下 Kotlin 代码通过 AES-CBC 生成有效的 CMS EnvelopedData 值:

import org.bouncycastle.cert.X509CertificateHolder
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter
import org.bouncycastle.cms.CMSAlgorithm
import org.bouncycastle.cms.CMSEnvelopedDataGenerator
import org.bouncycastle.cms.CMSProcessableByteArray
import org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder
import org.bouncycastle.cms.jcajce.JceKeyTransRecipientInfoGenerator

fun encrypt(plaintext: ByteArray, recipientCertificate: X509CertificateHolder): ByteArray {
    val cmsEnvelopedDataGenerator = CMSEnvelopedDataGenerator()

    val x509Certificate = JcaX509CertificateConverter()
        .getCertificate(recipientCertificate)
    val transKeyGen =
        JceKeyTransRecipientInfoGenerator(x509Certificate)
    cmsEnvelopedDataGenerator.addRecipientInfoGenerator(transKeyGen)

    val msg = CMSProcessableByteArray(plaintext)
    val encryptor = JceCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CBC).build()
    val bcEnvelopedData = cmsEnvelopedDataGenerator.generate(msg, encryptor)
    return bcEnvelopedData.encoded
}

但是如果我用 CMSAlgorithm.AES128_GCM 替换 CMSAlgorithm.AES128_CBCJceCMSContentEncryptorBuilder.build() 会抛出以下错误:

cannot create key generator: 2.16.840.1.101.3.4.1.6 KeyGenerator not available

该错误似乎表明不支持 AES-GCM-128,但对象 CMSAlgorithm.AES128_GCM 存在的事实向我表明这不可能——我一定是做错了什么。也许 IV 不是在幕后为我生成的,我必须以某种方式明确设置它?

我正在使用 org.bouncycastle:bcpkix-jdk15on:1.64

更新:我在 BouncyCastle 测试套件中发现 a test,它在 EnvelopedData 值中使用 AES-GCM,并且它们也在同一过程中将 CMSAlgorithm.AES128_GCM 传递给 JceCMSContentEncryptorBuilder方法。唯一的区别是他们在 .build() 之前调用 .setProvider("BC"),但我刚刚试过了,没有任何区别。

回答我的问题:

JceCMSContentEncryptorBuilder.setProvider()当然必须在.build()之前调用,但是如果provider没有注册,你必须传递一个org.bouncycastle.jce.provider.BouncyCastleProvider.

的实例