如何使用 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_CBC
,JceCMSContentEncryptorBuilder.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
.
的实例
我可以使用以下 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_CBC
,JceCMSContentEncryptorBuilder.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
.