简体   繁体   English

生成有效的CMS签名文件,并使用Java添加外部PKCS#1

[英]Generate valid CMS Signature file adding external PKCS#1 with Java

I'm generating CMS signature files with external PKCS#1 based on this thread . 我正在基于此线程使用外部PKCS#1生成CMS签名文件。

The first step is obtain the signed attributes from the original file to be signed in external application which is returning PKCS#1 byte array. 第一步是从要在外部应用程序中签名的原始文件中获取签名的属性,该外部应用程序将返回PKCS#1字节数组。

Then build standard org.bouncycastle.cms.SignerInfoGenerator with original file hash, signed data (PKCS#1) and certificate to add to CMS, and finally create the attached signature . 然后使用原始文件哈希,签名数据(PKCS#1)和要添加到CMS的证书构建标准的org.bouncycastle.cms.SignerInfoGenerator,最后创建附加的签名

But when i'd tried to validate it using this code: 但是,当我尝试使用以下代码对其进行验证时:

        String originalFile = "aG9sYQ0KYXNkYXMNCg0KYWZzDQo=";
        String cmsSignedFile = "MIAGCSqGSIb3DQEHAqCAMIACAQExDzANBg...j2Dwytp6kzQNwtXGO8QbWty1lOo8oYm+6LR8EWba3ikO/m9ol/G808vit9gAAAAAAAA==";
        byte[] signedByte = DatatypeConverter.parseBase64Binary(cmsSignedFile);

        Security.addProvider(new BouncyCastleProvider());

        CMSSignedData s = new CMSSignedData(new CMSProcessableByteArray(DatatypeConverter.parseBase64Binary(originalFile)), signedByte);
        SignerInformationStore signers = s.getSignerInfos();
        SignerInformation signerInfo = (SignerInformation)signers.getSigners().iterator().next();

        FileInputStream fis = new FileInputStream("C:/myCertificate.cer");
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        X509Certificate cert = (X509Certificate)cf.generateCertificates(fis).iterator().next();

        boolean result = signerInfo.verify(new JcaSimpleSignerInfoVerifierBuilder().setProvider("BC").build(cert.getPublicKey())); 
        System.out.println("Verified: "+result);


I get Verified: false 我得到验证:错误

I'm adding Content Type, Signing time, Message digest and OCSP as signed attributes and TSP Token as unsigned attribute (I'm not sure if this is right). 我将内容类型,签名时间,消息摘要和OCSP添加为已签名属性,将TSP令牌添加为未签名属性(我不确定这是否正确)。

I'm also trying to recover data from CMS signature, using the code below: 我还尝试使用以下代码从CMS签名中恢复数据:

        //load cms signed file with attached data
        CMSSignedData cms = new CMSSignedData(FileUtils.readFileToByteArray(new File("C:/tmp/tempFile1864328163858309463.cms")));

        System.out.println(cms.getSignerInfos().getSigners().iterator().next().getDigestAlgorithmID().getAlgorithm().getId());
        System.out.println(Hex.encodeHexString(cms.getSignerInfos().getSigners().iterator().next().getSignature()));

        //recover signer certificate info
        Store certs = cms.getCertificates();
        Collection<X509CertificateHolder> col = certs.getMatches(null);
        X509CertificateHolder []h1 = col.toArray(new X509CertificateHolder[col.size()]);
        X509CertificateHolder firmante = h1[0];
        System.out.println(firmante.getSubject());
        System.out.println(h1[1].getSubject());
        SignerInformation sinfo = cms.getSignerInfos().getSigners().iterator().next();

        //recover OCSP information
        //THIS FAILS :(
//          Store infocspbasic = cms.getOtherRevocationInfo(OCSPObjectIdentifiers.id_pkix_ocsp_basic);
//          Object basic = infocspbasic.getMatches(null).iterator().next();


        //recover signing time
        if (sinfo.getSignedAttributes() != null) {

            Attribute timeStampAttr = sinfo.getSignedAttributes().get(PKCSObjectIdentifiers.pkcs_9_at_signingTime);
            ASN1Encodable attrValue = timeStampAttr.getAttrValues().getObjectAt(0);

            final Date signingDate;
            if (attrValue instanceof ASN1UTCTime) {
                ASN1UTCTime time =  ASN1UTCTime.getInstance(attrValue);
                Date d = time.getDate();
                System.out.println("ASN1UTCTime:" + d);
            } else if (attrValue instanceof Time) {
                signingDate = ((Time) attrValue).getDate();
            } else if (attrValue instanceof ASN1GeneralizedTime) {
                System.out.println("ASN1GeneralizedTimeASN1GeneralizedTime");
            } else {
                signingDate = null;
            }
        }


        //recover timestamp TOken
        //unsigned attributes are null :(
        if (sinfo.getUnsignedAttributes() != null) {

            Attribute timeStampAttr = sinfo.getUnsignedAttributes().get(PKCSObjectIdentifiers.id_aa_signatureTimeStampToken);

            for (ASN1Encodable value : timeStampAttr.getAttrValues().toArray()) {
                TimeStampToken token = new TimeStampToken(new CMSSignedData(value.toASN1Primitive().getEncoded()));
                System.out.println(token.getTimeStampInfo().getGenTime());
            }

        }

But I can't retrieve OCSP response nor TSP Token information. 但是我无法检索OCSP响应或TSP令牌信息。 Additionally I've downloaded this viewer software to help verify it: 此外,我还下载了此查看器软件以帮助验证它:

P7S查看器

Any help would be very appreciated. 任何帮助将不胜感激。

I found a project named j4sign which implements CMS signature with external PKCS#1. 我找到了一个名为j4sign的项目,该项目使用外部PKCS#1实现CMS签名。 The link goes to the project's forum where I posted the code sample using their classes and the final correction to make the validation works. 链接转到项目的论坛,我在该论坛上使用其类和最终更正发布了代码示例,以使验证有效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM