【问题标题】:create PKCS7 with presigned data using bouncy castle使用充气城堡创建带有预签名数据的 PKCS7
【发布时间】:2017-01-15 15:17:58
【问题描述】:

我想使用 PKCS7 容器在 PDF 文件中创建分离签名。数据(哈希)已在使用私钥的不同设备上预先签名。我想创建一个包含签名数据的 PKCS7 以及带有公钥的证书。如果不提供私钥并让图书馆签署数据,我似乎无法创建带有充气城堡的 PKCS7。这似乎不起作用:

        InputStream inStream = new FileInputStream("1_public.pem");
        BufferedInputStream bis = new BufferedInputStream( inStream );

        CertificateFactory cf = CertificateFactory.getInstance("X.509");

        List<Certificate> certList = new ArrayList<Certificate>();
        Certificate certificate = cf.generateCertificate(bis);
        certList.add(certificate);
        Store certs = new JcaCertStore(certList);

        CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
        gen.addCertificates( certs );
        CMSProcessableInputStream msg = new CMSProcessableInputStream( new ByteArrayInputStream( "signedhash".getBytes() ) );

        CMSSignedData signedData = gen.generate(msg, false);
        byte[] pkcs7 = signedData.getEncoded() ) );

【问题讨论】:

  • 请说明它在什么方面不起作用。
  • pkcs7中缺少签名数据

标签: java bouncycastle pkcs#7


【解决方案1】:

我设法通过提供一个不签名的 ContentSigner 来做到这一点,实际上非常简单:

        InputStream inStream = new FileInputStream("1_public.pem");
        BufferedInputStream bis = new BufferedInputStream( inStream );

        CertificateFactory cf = CertificateFactory.getInstance("X.509");

        List<Certificate> certList = new ArrayList<Certificate>();
        Certificate certificate = cf.generateCertificate(bis);
        certList.add(certificate);
        Store certs = new JcaCertStore(certList);
        CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
        gen.addCertificates( certs );

        final byte[] signedHash = "signedhash".getBytes();

        ContentSigner nonSigner = new ContentSigner() {

            @Override
            public byte[] getSignature() {
                return signedHash;
            }

            @Override
            public OutputStream getOutputStream() {
                return new ByteArrayOutputStream();
            }

            @Override
            public AlgorithmIdentifier getAlgorithmIdentifier() {
                return new DefaultSignatureAlgorithmIdentifierFinder().find( "SHA256WithRSA" );
            }
        };

        org.bouncycastle.asn1.x509.Certificate cert = org.bouncycastle.asn1.x509.Certificate.getInstance(ASN1Primitive.fromByteArray(certificate.getEncoded()));
        JcaSignerInfoGeneratorBuilder sigb = new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().build());
        sigb.setDirectSignature( true );
        gen.addSignerInfoGenerator(sigb.build(nonSigner, new X509CertificateHolder(cert)));
        CMSProcessableInputStream msg = new CMSProcessableInputStream( new ByteArrayInputStream( "not used".getBytes() ) );

        CMSSignedData signedData = gen.generate(msg, false);
        byte[] pkcs7 = signedData.getEncoded();

【讨论】:

    【解决方案2】:

    如果“外部签名”由硬件设备执行,它可能还包含“签名属性”。在这种情况下,代码还必须包含:

    AttributeTable signedAttributes = signer.getSignedAttributes();
    signerInfoBuilder.setSignedAttributeGenerator(new SimpleAttributeTableGenerator(signedAttributes));     
    signatureGenerator.addSignerInfoGenerator(signerInfoBuilder.build(nonSigner, signCertificate));
    

    你也应该删除

    signatureGenerator.setDirectSignature(true)
    

    一个完整的例子可以在这里找到https://www.len.ro/work/attach-payload-into-detached-pkcs7-signature/。由于我花了很多时间寻找解决方案,而这篇文章提供了一个重要的线索,我认为我应该在一篇文章中补充我仍然错过的信息。谢谢。

    【讨论】:

    • 如果是您的网站,请在链接中添加从属关系
    猜你喜欢
    • 1970-01-01
    • 2014-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-02
    • 1970-01-01
    • 2015-12-23
    • 2015-05-04
    相关资源
    最近更新 更多