基于Bouncy Castle CMS公钥加密的技术咨询(附代码片段)
关于Bouncy Castle CMS公钥加密实现的技术解答
嘿,我看你正在基于Bouncy Castle实现CMS公钥加密,结合你给出的代码片段,我整理了几个核心技术点和常见问题的解决方案,帮你把流程补全并避坑:
一、补全核心加密流程
你的代码里JceKeyTransReci...部分截断了,完整的CMS公钥加密需要完成以下关键步骤,我给你补全了代码示例:
public static byte[] encryptData(byte[] data, X509Certificate encryptionCertificate) throws CertificateEncodingException, CMSException, IOException, NoSuchAlgorithmException, NoSuchProviderException { byte[] encryptedData = null; if (null != data && null != encryptionCertificate) { // 初始化CMS信封数据生成器 CMSEnvelopedDataGenerator cmsEnvelopedDataGenerator = new CMSEnvelopedDataGenerator(); // 配置密钥传输接收方生成器,优先使用安全的OAEP填充算法 JceKeyTransRecipientInfoGenerator jceKey = new JceKeyTransRecipientInfoGenerator(encryptionCertificate) .setProvider("BC") // 指定Bouncy Castle作为安全提供方 .setAlgorithm("RSA/ECB/OAEPWithSHA-256AndMGF1Padding"); // 将接收方生成器添加到CMS生成器中 cmsEnvelopedDataGenerator.addRecipientInfoGenerator(jceKey); // 用CMSProcessable包装原始待加密数据 CMSProcessableByteArray processableData = new CMSProcessableByteArray(data); // 生成加密后的CMS信封数据,指定对称加密算法(这里用AES-256-CBC) CMSEnvelopedData envelopedData = cmsEnvelopedDataGenerator.generate( processableData, new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES256_CBC) .setProvider("BC") .build() ); // 获取加密后的字节数组 encryptedData = envelopedData.getEncoded(); } return encryptedData; }
二、必须注意的关键细节
- 注册Bouncy Castle Provider:在调用任何Bouncy Castle API之前,一定要先注册安全提供方,否则会抛出
NoSuchProviderException:Security.addProvider(new BouncyCastleProvider()); - 算法选择要安全:
- 非对称加密别用默认的RSA PKCS#1 v1.5,优先选OAEP填充的算法(比如上面示例中的
RSA/ECB/OAEPWithSHA-256AndMGF1Padding),安全性更高 - 对称加密推荐用AES-256-GCM模式(
CMSAlgorithm.AES256_GCM),它提供认证加密,能同时保证机密性和完整性
- 非对称加密别用默认的RSA PKCS#1 v1.5,优先选OAEP填充的算法(比如上面示例中的
- 证书有效性检查:确保传入的
encryptionCertificate是有效的、包含可用公钥的证书,否则初始化JceKeyTransRecipientInfoGenerator时会抛出异常 - 异常处理要全面:除了你声明的几个异常,实际运行中还可能遇到
NoSuchAlgorithmException、NoSuchProviderException,建议根据业务需求捕获或声明这些异常
三、对应的解密实现参考
如果之后需要解密这段CMS加密数据,这里给你一个对应的解密代码示例(需要持有加密时用的证书对应的私钥):
public static byte[] decryptData(byte[] encryptedData, PrivateKey privateKey) throws CMSException, IOException, NoSuchProviderException { byte[] decryptedData = null; if (null != encryptedData && null != privateKey) { // 解析加密后的CMS信封数据 CMSEnvelopedData envelopedData = new CMSEnvelopedData(encryptedData); // 获取接收方信息集合,找到匹配私钥的接收方 RecipientInformationStore recipientInfos = envelopedData.getRecipientInfos(); for (RecipientInformation recipient : recipientInfos.getRecipients()) { decryptedData = recipient.getContent(new JceKeyTransRecipient(privateKey) .setProvider("BC")); break; // 找到匹配的私钥就停止遍历 } } return decryptedData; }
内容的提问来源于stack exchange,提问作者rschlachter
相关产品推荐
相关产品推荐

