如何使用BouncyCastle轻量级API生成cms封装数据



经过无数个小时的努力,我终于有了当前的工作代码,可以使用JCE/JCA:生成带有收件人信息的CMS封装(RSA-OAEP/PKCS#1)数据

String digest = "SHA-256";
String mgfDigest = "SHA-256";
// Data to encrypt
CMSTypedData msg = new CMSProcessableByteArray(data);
// Generator for my CMS enveloped data 
CMSEnvelopedDataGenerator envelopedDataGen = new CMSEnvelopedDataGenerator();
// Recipient Info Stuff
JcaAlgorithmParametersConverter paramsConverter = new JcaAlgorithmParametersConverter();
OAEPParameterSpec oaepSpec = new OAEPParameterSpec(digest, "MGF1", new MGF1ParameterSpec(mgfDigest), PSource.PSpecified.DEFAULT);
AlgorithmIdentifier oaepAlgId = paramsConverter.getAlgorithmIdentifier(PKCSObjectIdentifiers.id_RSAES_OAEP, oaepSpec);
envelopedDataGen.addRecipientInfoGenerator(
        new JceKeyTransRecipientInfoGenerator(
                getCert(), 
                oaepAlgId).setProvider("BC"));
/*
  * Generate CMS-Data
  * CMSOutputEncryptor is my own Class implementing OutputEncryptor
  */
CMSEnvelopedData ed = envelopedDataGen.generate(
        msg, 
        new CMSOutputEncryptor());
byte[] encoded = ed.getEncoded();

这正如预期的那样工作,但由于它使用JCE,我的客户需要安装无限强度的api才能使用此代码。我更喜欢一种克服这些需求的方法,因为我的大多数客户都是拇指。。。

也许有人可以给我看一段代码,它使用纯BouncyCastle的方式来做同样的事情,这样就不需要安装无限强度的api了?

请注意,我不确定这是否在所有国家/地区/对所有客户都合法

如果你想取消限制,你可以使用一些反射魔法。这就是我在框架中的做法(部分取自:https://github.com/jruby/jruby/blob/0c345e1b186bd457ebd96143c0816abe93b18fdf/core/src/main/java/org/jruby/util/SecurityHelper.java):

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
public class UnlimitedStrengthHelper {
    public static void removeCryptoStrengthRestriction() {
        try {
            if (Cipher.getMaxAllowedKeyLength("AES") < 256) {
                Class jceSecurity = Class.forName("javax.crypto.JceSecurity");
                Field isRestricted = jceSecurity.getDeclaredField("isRestricted");
                if (Modifier.isFinal(isRestricted.getModifiers())) {
                    Field modifiers = Field.class.getDeclaredField("modifiers");
                    modifiers.setAccessible(true);
                    modifiers.setInt(isRestricted, isRestricted.getModifiers() & ~Modifier.FINAL);
                    modifiers.setAccessible(false);
                }
                isRestricted.setAccessible(true);
                isRestricted.setBoolean(null, false);
                isRestricted.setAccessible(false);
            }
        } catch (ClassNotFoundException | IllegalAccessException | IllegalArgumentException
                | NoSuchAlgorithmException | NoSuchFieldException | SecurityException ex) {
            System.out.println("It is not possible to use unrestricted policy with this JDK, "
                    + "consider reconfiguration: " + ex.getLocalizedMessage());
        }
    }
}

代码首先检查限制是否存在(在这种情况下,您不能使用AES256)。然后,它获取JceSecurity类及其isRestricted字段。它确保我们可以访问此字段,并最终将其值设置为false。

顺便说一下。,谢谢你的CMS示例,它帮了我很多。

最新更新