I'm trying to generate a pdf with LTV enabled. I generate a pkcs7 object with all the attributes necesary included the signerInfo object. The signature generated is valid but not LTV enabled. According to the PDF reference manual i need to include validation info (CRLS or OCSP...) and based on rfc3852 this content goes in the signedAttributes object and it must contain a content-type attribute and a message-digest attribute. My question is how to compute the message-digest value and is it necesary to sign alongside the pdf content?
Note: the adbe-revocationInfoArchival object containing the CRLs seems to be correct since acrobat reads the revocation info directly from the file. The only issue i seem to have is the message-digest included in the signedAttrs object and/or the signature value is not computed correctly. RFC is not very clear on what that message-digest should be or if it should be included in the digest that will be signed with the signers private key.
CodePudding user response:
After some back and forth in the comments to the question I'm still not sure what information you need, so here a few thoughts in general on the structure and contents of non-trivial CMS signature containers for PDF signatures.
The Specifications
First off, though, some words on the specifications to use. You mention the PDF reference manual and rfc3852. Both actually are not state-of-the-art anymore, but interestingly one less than the other.
Originally the Adobe PDF References for PDF up to 1.7 were the documentation to look at. Unfortunately Adobe saw these references as not normative in nature, i.e. if the current Reference and the current Acrobat version disagreed on something, the program was correct, not the Reference!
The latest Adobe PDF Reference (for PDF 1.7) referred to RFC 2315 for the structure of the signature container.
Then Adobe transferred the authority over the format PDF to the International Organization for Standardization (ISO) who in 2008 published the first normative PDF specification, ISO 32000-1, which was very similar to the last PDF Reference in content but adopted the RFC'ish language.
ISO 32000-1 refers both to RFC 3852 and RFC 2315 for the structure of the signature container. Which is weird, but most likely the remaining RFC 2315 reference was an oversight.
In 2017 the ISO published a PDF specification for PDF 2.0, ISO 32000-2, with a number of relevant changes, also in the context of signing.
ISO 32000-2 refers to RFC 5652 for the structure of the signature container for adbe.pkcs7.detached signatures and to ETSI EN 319 122 for the structure of the signature container for ETSI.CAdES.detached signatures.
In 2020 the ISO updated ISO 32000-2 with a number of clarifications; the references for the signature container specification remained the same.
Thus, currently you should look at ISO 32000-2:2020 and RFC 5652.
CMS Signature Containers
In a late comment you say
I want to know how do i add these attributes to the final digest to sign. I'm using SHA to digest the pdf, then sign it with the rsa private key and build the pkcs7 structure including the certificate chain, the signed message and a timestamp as an unsigned attribute.
This procedure can only create simple signature containers without signed attributes as only in these simple containers the document hash is signed directly. But the adbe-revocationInfoArchival attribute you want to add must be a signed attribute, and as soon as signed attributes are involved, the document hash value is not signed directly anymore.
The CMS signature container contains a SignedData
object with exactly one SignerInfo
object. That SignerInfo
object is defined as
SignerInfo ::= SEQUENCE {
version CMSVersion,
sid SignerIdentifier,
digestAlgorithm DigestAlgorithmIdentifier,
signedAttrs [0] IMPLICIT SignedAttributes OPTIONAL,
signatureAlgorithm SignatureAlgorithmIdentifier,
signature SignatureValue,
unsignedAttrs [1] IMPLICIT UnsignedAttributes OPTIONAL }
(RFC 5652 section 5.3. "SignerInfo Type")
In a signature container created by your working code the OPTIONAL signedAttrs
are absent and the signature
value is calculated immediately for the document hash.
As soon as there are signed attributes, though, the OPTIONAL signedAttrs
is not absent anymore, instead it is a SET
of Attribute
instances including at least
- a content-type attribute with id-data as value,
- a message-digest attribute with the digest value of the to-be-signed PDF byte ranges as value,
- and in your case an adbe-revocationInfoArchival attribute with the revocation information as value.
In this case the signature
value is not calculated immediately for the document hash anymore but instead for the hash value of the signedAttrs
!
To be more exact, it is calculated for the hash value of the complete DER encoding thereof, and not with the IMPLICIT [0] tag but with an EXPLICIT SET OF tag.
Thus, after using SHA to digest the pdf you instead of signing it with the rsa private key and building the pkcs7 structure proceed by
- building the set of signed attributes with at least the attribute entries enumerated above, DER encoding that set and hashing it,
- signing that hash value of the signed attributes with your private key, and
- building the CMS signature container structure with these signed attributes and this signature value, and also with the certificate chain.
Additionally you may add a signature time stamp.