Pades Signature使用PDFBox ETSI验证

huangapple go评论88阅读模式
英文:

Pades Signature using PDFBox ETSI validation

问题

我使用 PDFBOX 创建了一个 PDF PAdES 签名,并且正在使用 ETSI 在线验证器 [1](需要注册)进行验证,目前报告中只有两个错误,但我对这些错误是什么或者如何修复它们感到有些迷茫。

这是 ETSI 在线验证器的报告:

[![][2]][2]

这是我用于签名的代码:
(以下为代码部分,不提供翻译)

我不太确定问题可能出在哪里,或者为什么会生成这些问题。起初我有 5 个错误,但现在只剩下这两个,因此对于任何建议我都非常感谢。

  [1]: https://signatures-conformance-checker.etsi.org/protected/upload.php?sigtype=padesconf
  [2]: https://i.stack.imgur.com/yzKkd.png
英文:

I created a PDF PAdES signature using PDFBOX and I am using the ETSI online validator 1 (it requires registration) and right now I am getting only two errors on the report but im kind of lost about what they are or how can I fix them.

This is the etsi online validator report:

Pades Signature使用PDFBox ETSI验证

And this is the code I am using to sign:

@Override
    public byte[] sign(InputStream content) throws IOException {
        try {
            CMSSignedDataGenerator signGenerator = new CMSSignedDataGenerator();
            X509Certificate userCert = (X509Certificate) this.certificateChain[0];
            ContentSigner mySigner = new CustomSigner(this.signerKeyHandle);
            // TODO check to use cavium as digest provider
            MessageDigest md = MessageDigest.getInstance("SHA-256", "Cavium");
            md.update(userCert.getEncoded());
            byte[] userCertHash = md.digest();
            X509CertificateHolder issuerCert = new X509CertificateHolder(this.certificateChain[1].getEncoded());
            // IssuerSerial is = new IssuerSerial(issuerCert.get,
            // issuerCert.getSerialNumber());
            ESSCertIDv2 certid = new ESSCertIDv2(new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha256),
                    userCertHash);
            ESSCertIDv2[] essCert1Arr = { certid };
            SigningCertificateV2 sigcert = new SigningCertificateV2(certid);
            final DERSet attrValues = new DERSet(sigcert);
            Attribute attr = new Attribute(PKCSObjectIdentifiers.id_aa_signingCertificateV2, attrValues);
            ASN1EncodableVector v = new ASN1EncodableVector();
            v.add(attr);
            AttributeTable atttributeTable = new AttributeTable(v);
             //Create a standard attribute table from the passed in parameters - certhash
             CMSAttributeTableGenerator attrGen = new DefaultSignedAttributeTableGenerator(atttributeTable){
                protected Hashtable createStandardAttributeTable(Map parameters)
                {
                    Hashtable result = super.createStandardAttributeTable(parameters);
                    result.remove(CMSAttributes.signingTime);
                    return result;
                }
            };
            JcaSignerInfoGeneratorBuilder signerBuilder = new JcaSignerInfoGeneratorBuilder( new JcaDigestCalculatorProviderBuilder().build());
            signerBuilder.setSignedAttributeGenerator(attrGen);
            SignerInfoGenerator signerInfoGenerator = signerBuilder.build(mySigner, userCert);
            signGenerator.addSignerInfoGenerator(signerInfoGenerator);
            signGenerator.addCertificates(new JcaCertStore(Arrays.asList(certificateChain)));
            CMSProcessableInputStream msg = new CMSProcessableInputStream(content);
            CMSSignedData signedData = signGenerator.generate(msg, false);
            return signedData.getEncoded();
        } catch (GeneralSecurityException | CMSException | OperatorCreationException e) {
            System.err.println(e.getMessage());
            throw new RuntimeException("unable to sign pdf!");
        }
    }

Im not quite sure where those problems could be or why are they generated, at the beginning I had 5 and right now im only down to these two, so any input will be greatly appreciated

答案1

得分: 4

The Original Question

你使用了 DefaultSignedAttributeTableGenerator

signerBuilder.setSignedAttributeGenerator(new DefaultSignedAttributeTableGenerator(new AttributeTable(v)));

根据它的 JavaDocs,它会执行以下操作:

/* 从传入的参数创建标准属性表 - 通常会包括 contentType、signingTime、messageDigest 以及 CMS 算法保护。
 * 如果使用了带有 AttributeTable 的构造函数,则其中针对 contentType、signingTime 和 messageDigest 的条目将会覆盖生成的条目。

特别地,它会创建一个 signingTime 签名属性。

但是对于(非遗留的)PAdES 签名,嵌入的 CMS 容器不得包含 signingTime 属性,详见 ETSI EN 319 142-1 第 6.3 节的基线签名要求:

> SPO:CMS 签名中不应包含 signing-time 属性

而且原始的 ETSI TS 102 778-3 第 4.5.3 节对于 PAdES-BES 和 PAdES-EPES 签名要求:

> 不得使用 signing-time 属性。

(严格来说,当前的 ETSI EN 319 142-2 PAdES-E-BES 和 PAdES-E-EPES 配置似乎不再禁止使用,它们只是 建议 使用 M 签名字典条目代替。但是检查 BES/EPES 的软件通常仍然基于旧的 TS,而该 TS 确实禁止,参见上文。而且现在一般应该使用基线签名...)

因此,你应该使用一个不包含签名时间属性的 CMSAttributeTableGenerator 实现,例如通过复制 DefaultSignedAttributeTableGenerator 的代码并从其 createStandardAttributeTable 方法中删除签名时间属性。

The Updated Question

在评论中,你提到在解决了上述问题后仍然存在一个错误:

> 现在只是一个错误,是数字 63,它说的是 Location-{CodeTest}:Contents/CAdESSignature/content/signedData/signerInfos/signerInfo1/signedAttrs/attribute[4]/attrValues/NotKnownComponent1-{ForAllTheChildrenDo} 已到达未知组件。因此,其子项及其处理对 TLCC 来说是未知的。不会对此组件进行进一步检查

你的 SignerInfo 中的最后一个(第四个)签名属性是根据 RFC 6211(2011 年 4 月)的规定的 算法标识符保护属性。考虑到 ETSI 签名符合性检查器的年代,它可能确实不认识这个属性。

如果你想让符合性检查器不显示该错误,只需像删除签名时间属性一样,从 DefaultSignedAttributeTableGenerator 的标准属性表中删除该属性。

英文:

The Original Question

You use the DefaultSignedAttributeTableGenerator:

signerBuilder.setSignedAttributeGenerator(new DefaultSignedAttributeTableGenerator(new AttributeTable(v)));

According to its JavaDocs it will

/* Create a standard attribute table from the passed in parameters - this will
 * normally include contentType, signingTime, messageDigest, and CMS algorithm protection.
 * If the constructor using an AttributeTable was used, entries in it for contentType, signingTime, and
 * messageDigest will override the generated ones.

In particular it will create a signingTime signed attribute.

But for (non-legacy) PAdES signatures the embedded CMS containers must not contain a signingTime attribute, see ETSI EN 319 142-1 section 6.3 for Baseline signatures

> SPO: signing-time attribute in CMS signature ... shall not be present

and already the original ETSI TS 102 778-3 section 4.5.3 for PAdES-BES and PAdES-EPES signatures requires that

> the signing-time attribute shall not be used.

(Strictly speaking the current ETSI EN 319 142-2 PAdES-E-BES and PAdES-E-EPES profiles do not appear to forbid the use anymore, they merely recommend using the M signature dictionary entry instead. But software checking for BES/EPES usually still are based on the old TS which does forbid, see above. And nowadays one should go for Baseline signatures anyways...)

Thus, you should use a CMSAttributeTableGenerator implementation instead that does not include the signing time attribute, e.g. by copying the DefaultSignedAttributeTableGenerator code and removing the signing time from its createStandardAttributeTable method.

The Updated Question

In a comment you say that after fixing the issue above one error remains:

> Right now its only an error and its the number 63 that says Location-{CodeTest}:Contents/CAdESSignature/content/signedData/signerInfos/signerInfo1/signedAttrs/attribute[4]/attrValues/NotKnownComponent1-{ForAllTheChildrenDo} An unknown component has been reached. Consequently, its children and their processing are unknown to the TLCC. No further checks will be done to this component

The last (fourth) signed attribute in your SignerInfo is an Algorithm Identifier Protection Attribute according to RFC 6211 from April 2011. Considering the age of the ETSI signature conformance checker it may indeed not know this attribute.

If you want the conformance checker to not display that error, simply remove that attribute from the DefaultSignedAttributeTableGenerator's standard attribute table just like you removed the signing time attribute.

huangapple
  • 本文由 发表于 2020年10月22日 10:27:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/64474359.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定