有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java使用bouncy castle创建带有预签名数据的PKCS7

我想使用PKCS7容器在PDF文件中创建分离的签名。数据(散列)是使用私钥在不同的设备上预先签名的。我想创建一个PKCS7,其中包含签名数据以及带有公钥的证书。如果不提供私钥并让库对数据进行签名,我似乎无法创建带有bouncy castle的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() ) );

共 (2) 个答案

  1. # 1 楼答案

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

    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/。因为我花了很多时间寻找解决方案,而这篇文章提供了一个重要的线索,所以我认为我应该补充我在一篇文章中仍然遗漏的信息。谢谢

  2. # 2 楼答案

    我通过提供一个不签名的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();