【问题标题】:How to extend/add a Bouncycastle digest algorithm for CMS?如何为 CMS 扩展/添加 Bouncycastle 摘要算法?
【发布时间】:2018-03-23 20:44:34
【问题描述】:

使用 Java,我想使用 RSA 对给定的 byte[] hash 进行加密签名,并以 Cryptographic Message Syntax (CMS) 格式返回 byte[] signature

我为此使用Bouncycastle Java API (BC),并面临NONEwithRSA 签名类型不存在的问题。 (java.lang.IllegalArgumentException: Unknown signature type requested: NONEWITHRSA)。

不幸的是,我无法更改输入或所需的输出格式,因此我需要扩展/添加到现有的 BC 算法,以便我可以使用NONEwithRSA 而不是所有其他现有的(例如SHA256withRSA)。我该怎么做呢?我在 BC 文档中没有找到任何示例。

我想要的用法与此类似

byte[] doSigningCMS(byte[] data, X509Certificate cert, PrivateKey key) throws Exception {

    CMSSignedDataGenerator signGen = new CMSSignedDataGenerator();
    CMSTypedData content = new CMSProcessableByteArray(data);

    ContentSigner signer = new JcaContentSignerBuilder("NONEwithRSA").build(key);

    DigestCalculatorProvider dcp = new JcaDigestCalculatorProviderBuilder().build();

    signGen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(dcp).build(signer, cert));

    return signGen.generate(content, false).getEncoded();
}

到目前为止我所尝试的

  • 通过“复制”一堆 BC 代码和“假”SHA256withRSA 为 JCA 添加我自己的提供程序,以基本上返回 NoneDigest 而不是 SHA256Digest。但这似乎是非常错误的。
  • 使用 ((BouncyCastleProvider) Security.getProvider("BC")).addAlgorithm(ALG_ALIAS, NoneDigest.class.getName()) 将我自己的算法添加到 BC,这似乎不起作用(找不到算法)

我希望得到一些建议和指导来做到这一点(如果可能的话)“正确的方式”。谢谢。

【问题讨论】:

  • “NoneWithRSA”签名算法的规范在哪里?我很想从自定义 JcaContentSignerBuilder 开始。

标签: java cryptography bouncycastle


【解决方案1】:

“NoneWithRSA”是没有添加摘要算法的OID的RSA数字签名。加密提供者也不制作摘要。基本上它是使用私钥的 PKCS#1_v15 加密。

你可以在这个 OpenJDK 测试https://github.com/ddopson/openjdk-test/blob/master/java/security/Signature/NONEwithRSA.java中看到它是如何工作的

由于 Bouncycastle 似乎不支持它,我认为您可以使用默认提供程序而不是使用 JcaContentSignerBuilder 来提供自己的 ContentSigner 实现

假设输入数据已经被散列,所以如果你正在做一个PKCS#1签名,我认为你需要提供签名算法。查看RFC3477 它取决于使用的哈希算法。

A.2.4 RSASSA-PKCS1-v1_5

RSASSA-PKCS1-v1_5 的对象标识符应是 下列的。 OID的选择取决于hash的选择 算法:MD2、MD5、SHA-1、SHA-256、SHA-384 或 SHA-512。


String sigAlgo = "SHA256WithRSAEncryption"; // "SHA256WithRSAEncryption" for SHA256, "SHA1WithRSAEncryption" for SHA1, etc.
ContentSigner signer = new CustomContentSigner(key, sigAlgo );

public class CustomContentSigner implements ContentSigner {

    private AlgorithmIdentifier algorithmIdentifier;
    private Signature signature;
    private ByteArrayOutputStream outputStream;

    public CustomContentSigner(PrivateKey privateKey, String sigAlgo) {
        //Utils.throwIfNull(privateKey, sigAlgo);
       this.algorithmIdentifier = new DefaultSignatureAlgorithmIdentifierFinder().find(sigAlgo);

        try {
            this.outputStream = new ByteArrayOutputStream();
            this.signature = Signature.getInstance("NONEwithRSA");
            this.signature.initSign(privateKey);
        } catch (GeneralSecurityException gse) {
            throw new IllegalArgumentException(gse.getMessage());
        }
    }

    @Override
    public AlgorithmIdentifier getAlgorithmIdentifier() {
        return algorithmIdentifier;
    }

    @Override
    public OutputStream getOutputStream() {
        return outputStream;
    }

    @Override
    public byte[] getSignature() {
        try {
            signature.update(outputStream.toByteArray());
            return signature.sign();
        } catch (GeneralSecurityException gse) {
            gse.printStackTrace();
            return null;
        }
    }
}

免责声明:我不知道它是否有效,但您可以尝试一下

【讨论】:

  • 感谢您的提示,CustomContentSigner 似乎是一个好的开始。但是,我仍然有DefaultSignatureAlgorithmIdentifierFinder 找不到(在BC 中不存在)NONEwithRSA 算法的问题。我没有看到向 BC 提供该算法的方法。
  • 我认为在使用“NONEwithRSA”签名之前,您应该根据您应用于数据的摘要算法提供签名算法。查看更新的答案
  • @fdomig,你终于解决了这个问题吗?我很好奇这是否真的有效
  • 很遗憾还没有。
  • 我想我找到了适合我的解决方案。但不幸的是,我使用RSABlindEngine 创建我的签名,然后在手动步骤中创建 CMS 结构。但是您将我引向正确的方向,因此我接受您的回答。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-26
  • 2021-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-23
相关资源
最近更新 更多