【问题标题】:How to use BouncyCastle lightwigth API to generate cms enveloped data如何使用 BouncyCastle lightwigth API 生成 cms 封装数据
【发布时间】:2016-12-05 19:36:38
【问题描述】:

经过无数个小时的挣扎,我终于有了当前的工作代码,可以使用 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?

【问题讨论】:

    标签: java bouncycastle pkcs#1


    【解决方案1】:

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

    如果你想取消限制,你可以使用一些反射魔法。这就是我在我的框架中的做法(部分取自: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 示例,它对我帮助很大。

    【讨论】:

    • 感谢此代码,但 AFAIK 这将不再起作用,因为静态字段终于出现了。请查看github.com/jruby/jruby/issues/4101。最后,我决定提供一个启用了无限强度 api 的完整 java jre。但很高兴知道我的一段代码对你有帮助。
    • 这一行将修饰符设置为非最终的:modifiers.setInt(isRestricted, isRestricted.getModifiers() & ~Modifier.FINAL);
    猜你喜欢
    • 2013-12-30
    • 1970-01-01
    • 1970-01-01
    • 2022-09-25
    • 2012-04-13
    • 1970-01-01
    • 2013-10-24
    • 2017-04-06
    • 1970-01-01
    相关资源
    最近更新 更多