【问题标题】:How to convert detached CAdES signature to enveloped using BC?如何使用 BC 将分离的 CAdES 签名转换为封装?
【发布时间】:2013-09-05 06:56:31
【问题描述】:

我的 java 小程序能够使用分离类型的 Bouncy Castle 1.4.9 生成 CMSSignedData。然后将字节数组 sigData.getEncoded() 存储在服务器上的一个表中(它可以访问未包含的内容数据)。现在我想在服务器中创建封装的 CMSSignedData,以便用户下载 .p7m 文件。

我需要开发的函数有分离签名的字节数组和内容数据的字节数组,并且必须返回一个CaDES封装签名的字节数组,用于下载.p7m文件。

问题是我无法将分离的签名者转换为信封的签名者。

这是我在小程序中使用的一些代码: signCAdeS 使用分离签名对文档进行签名,然后调用 attach(仅用于测试)将分离转换为封装但未成功:使用 Dike 打开创建的 .p7m 文件无法查看内容数据。

private byte[] signCAdES(byte[] aDocument, PrivateKey aPrivateKey, Certificate[] certChain)
        throws GeneralSecurityException {
    byte[] digitalSignature = null;
    try {

        Security.addProvider(new BouncyCastleProvider());
        ArrayList<X509Certificate> certsin = new ArrayList<X509Certificate>();
        for (int i = 0; i < certChain.length; i++) {
            certsin.add((X509Certificate) certChain[i]);
        }
        X509Certificate cert = certsin.get(0);
        //Nel nuovo standard di firma digitale e' richiesto l'hash del certificato di sottoscrizione:
        String digestAlgorithm = "SHA-256";
        String digitalSignatureAlgorithmName = "SHA256withRSA";
        MessageDigest sha = MessageDigest.getInstance(digestAlgorithm);
        byte[] digestedCert = sha.digest(cert.getEncoded());

        //Viene ora create l'attributo ESSCertID versione 2 cosi come richiesto nel nuovo standard:
        AlgorithmIdentifier aiSha256 = new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha256);
        ESSCertIDv2 essCert1 = new ESSCertIDv2(aiSha256, digestedCert);
        ESSCertIDv2[] essCert1Arr = {essCert1};
        SigningCertificateV2 scv2 = new SigningCertificateV2(essCert1Arr);
        Attribute certHAttribute = new Attribute(PKCSObjectIdentifiers.id_aa_signingCertificateV2, new DERSet(scv2));

        //Aggiungiamo l'attributo al vettore degli attributi da firmare:
        ASN1EncodableVector v = new ASN1EncodableVector();
        v.add(certHAttribute);
        AttributeTable at = new AttributeTable(v);
        CMSAttributeTableGenerator attrGen = new DefaultSignedAttributeTableGenerator(at);

        //Creaiamo l'oggetto che firma e crea l'involucro attraverso le librerie di Bouncy Castle:
        SignerInfoGeneratorBuilder genBuild = new SignerInfoGeneratorBuilder(new BcDigestCalculatorProvider());
        genBuild.setSignedAttributeGenerator(attrGen);

        //Si effettua la firma con l'algoritmo SHA256withRSA che crea l'hash e lo firma con l'algoritmo RSA:
        CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
        ContentSigner shaSigner = new JcaContentSignerBuilder("SHA256withRSA").build(aPrivateKey);
        SignerInfoGenerator sifGen = genBuild.build(shaSigner, new X509CertificateHolder(cert.getEncoded()));
        gen.addSignerInfoGenerator(sifGen);
        X509CollectionStoreParameters x509CollectionStoreParameters = new X509CollectionStoreParameters(certsin);
        JcaCertStore jcaCertStore = new JcaCertStore(certsin);
        gen.addCertificates(jcaCertStore);

        CMSTypedData msg = new CMSProcessableByteArray(aDocument);
        CMSSignedData sigData = gen.generate(msg, false); // false=detached

        byte[] encoded = sigData.getEncoded();

        FileOutputStream fos = new FileOutputStream("H:\\prova2.txt.p7m");
        fos.write(attach(aDocument, encoded));
        fos.flush();
        fos.close();
        digitalSignature = encoded;


    } catch (CMSException ex) {
        ex.printStackTrace();
    } catch (IOException ex) {
        ex.printStackTrace();
    } catch (OperatorCreationException ex) {
        ex.printStackTrace();
    }
    return digitalSignature;
}

这里是附加函数:

public static byte[] attach(byte[] originalData, byte[] detached) {
    try {
        ASN1InputStream in = new ASN1InputStream(detached);

        CMSSignedData sigData = new CMSSignedData(new CMSProcessableByteArray(originalData), in);

        return sigData.getEncoded();
    } catch (Exception e) {
        return null;
    }
}

【问题讨论】:

    标签: java cryptography digital-signature bouncycastle


    【解决方案1】:

    这个回复来的有点晚。您肯定会找到替代方案,因为无法将分离的 CAdES 转换为封装

    查看CAdES 签名的SignedData 节点的ASN.1 结构,如RFC 3852 -CMS 中定义的那样

    SignedData 包括 encapContentInfo,其中包含要为封装签名签名但不存在于分离签名中的原始数据。 由于SignedData已签名,因此无法添加原始数据以将分离的转换为包络

    注意:正确的术语是enveloping,因为签名包装了数据。 封装的签名将嵌入到数据中

    【讨论】:

      【解决方案2】:

      改编自http://bouncy-castle.1462172.n4.nabble.com/Add-signed-content-to-detached-signatures-td1467150.html

          public static byte[] attach(byte[] originalData, byte[] detached) throws IOException {
              try (ASN1InputStream in = new ASN1InputStream(detached);) {
                  BERSequence seqContentData = (BERSequence) in.readObject();
      
                  ContentInfo contentInfo = ContentInfo.getInstance(seqContentData);
                  SignedData sdDetached = new SignedData((ASN1Sequence) contentInfo.getContent());
                  ContentInfo encapContentInfo = new ContentInfo(CMSObjectIdentifiers.data, new BEROctetString(originalData));
      
                  SignedData sdAttached = new SignedData(
                          sdDetached.getVersion(),
                          sdDetached.getDigestAlgorithms(), 
                          encapContentInfo, 
                          sdDetached.getCertificates(), 
                          sdDetached.getCRLs(), 
                          sdDetached.getSignerInfos());
                  ContentInfo contentInfoAttached = new ContentInfo(PKCSObjectIdentifiers.signedData, sdAttached);
                  return contentInfoAttached.getEncoded();
              }
          } 
      

      使用 BC 1.64 测试

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-01-09
        • 1970-01-01
        • 1970-01-01
        • 2022-07-13
        • 1970-01-01
        相关资源
        最近更新 更多