Pades Signature using PDFBox ETSI validation

1.1k Views Asked by At

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:

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

There are 1 best solutions below

5
On BEST ANSWER

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.