I am trying to sign a PDF with BouncyCastle CMS. Signing works, but Adobe Reader tells me it is not LTV-ready.
As far as I can see, the CRLs are embedded in the CMS SignedData. The certficates are embedded too. A timestamp also is embedded.
The signature is a detached signature and put in the "reserved space".
Why is the signature still not LTV-ready? Am I doing something obvious wrong?
Signed Test-PDF: http://www.filedropper.com/outputx
Code:
CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
// CertificateChain
List<Certificate> certList = Arrays.asList(certChain);
try {
Hashtable signedAttrs = new Hashtable();
X509Certificate signingCert = (X509Certificate) certList.get(0);
gen.addSignerInfoGenerator(new JcaSimpleSignerInfoGeneratorBuilder().setProvider("BC")
.setSignedAttributeGenerator(new AttributeTable(signedAttrs))
.build("SHA256withRSA", privKey, signingCert));
gen.addCertificates(new JcaCertStore(certList));
boolean embedCrls = true;
if (embedCrls) {
X509CRL[] crls = fetchCRLs(signingCert);
for (X509CRL crl : crls) {
gen.addCRL(new JcaX509CRLHolder(crl));
}
}
// gen.addOtherRevocationInfo(arg0, arg1);
CMSProcessableByteArray processable = new CMSProcessableByteArray(IOUtils.toByteArray(content));
CMSSignedData signedData = gen.generate(processable, false);
if (tsaClient != null) {
signedData = signTimeStamps(signedData);
}
return signedData.getEncoded();
} catch (Exception e) {
throw new RuntimeException(e);
}
In interoperable PDF signatures there are two ways to add validation related information, and neither of them uses the default CMS way of adding CRLs that your code uses.
The old, ISO 32000-1 style "PKCS#7 Signatures as used in ISO 32000" (later based on CMS instead of PKCS#7) are specified to include revocation information in a dedicated signed attribute for an OID registered by Adobe:
12.8.3.3.2 Revocation Information
The adbe Revocation Information attribute:
adbe-revocationInfoArchival OBJECT IDENTIFIER ::= { adbe(1.2.840.113583) acrobat(1) security(1) 8 }
The value of the revocation information attribute can include any of the following data types:
- Certificate Revocation Lists (CRLs), described in RFC 3280 (see the Bibliography): CRLs are generally large and therefore should not be embedded in the PKCS#7 object.
- Online Certificate Status Protocol (OCSP) Responses, described in RFC 2560, X.509 Internet Public Key Infrastructure Online Certificate Status Protocol—OCSP (see the Bibliography): These are generally small and constant in size and should be the data type included in the PKCS#7 object.
- Custom revocation information: The format is not prescribed by this specification, other than that it be encoded as an OCTET STRING. The application should be able to determine the type of data contained within the OCTET STRING by looking at the associated OBJECT IDENTIFIER.
adbe's Revocation Information attribute value has ASN.1 type RevocationInfoArchival:
RevocationInfoArchival ::= SEQUENCE { crl [0] EXPLICIT SEQUENCE of CRLs, OPTIONAL ocsp [1] EXPLICIT SEQUENCE of OCSP Responses, OPTIONAL otherRevInfo [2] EXPLICIT SEQUENCE of OtherRevInfo, OPTIONAL } OtherRevInfo ::= SEQUENCE { Type OBJECT IDENTIFIER Value OCTET STRING }
(Obviously this is merely Pseudo-ASN.1...)
As this structure is the value of a signed attribute, revocation information must be fetched before signing to be added like this.
For their PAdES signatures ETSI specified extra PDF structures to be added to signed PDF documents which can carry extra validation related information, see ETSI EN 319 142. These structures later were integrated in ISO 32000-2:
12.8.4.3 Document Security Store (DSS)
The document security store (DSS), when present, shall be a dictionary that shall be the value of a DSS key in the document catalog dictionary (see 7.7.2, "Document catalog dictionary"). This dictionary may contain:
- an array of all certificates used for the signatures, including timestamp signatures, that occur in the document. It shall also hold all the auxiliary certificates required to validate the certificates participating in certificate chain validations.
- an array of all Certificate Revocation Lists (CRL) (see Internet RFC 5280) used for some of the signatures, and
- an array of all Certificate Status Protocol (OCSP) responses (see Internet RFC 6960) used for some of the signatures.
- a VRI key whose value shall be a dictionary containing one VRI dictionary (validation-related information) for each signature represented in CMS format.
Any VRI dictionaries, if present, shall be located in document incremental update sections. If the signature dictionary to which a VRI dictionary applies is itself in an incremental update section, the DSS/VRI update shall be done later than the signature update. The inclusion of VRI dictionary entries is optional. All validation material referenced in VRI entries is included in DSS entries too.
...
As you can read already here, this structure is designed for adding information after signing. This goes along with the ETSI favoring revocation information generated after the signature for validation.
You mention PDFBox in your tags, so you appear to use PDFBox for signing.
To add pre-fetched validation data to the signed adbe-revocationInfoArchival
attribute, you merely have to add an attribute as defines above to the signedAttrs
of your code.
To add data in document security stores (DSS) you can use the code of the PDFBox example AddValidationInformation
as mentioned by @Tilman in a comment.