Step 7 of the flow gives you B-B, and B-T if a timestamp went into the CMS. That is not B-LTA, and it does not have to be: how far you go is a choice, and for many integrations B-T is the intended level. Each rung up is something that is added to the file; the hash signing at Cleverbase is identical at every level. This chapter says what each rung puts in the file, what it proves, and what it needs.
Pick a rung to see what it adds to the file, what it proves, what validating it still needs from outside, and where to look to tell which rung a file in front of you is really on.
The rungs
B-B, the signature
In the file The CMS with signed attributes and the signature value in /Contents. Proves who signed what; the time is only the claimed /M. Validation depends on the certificate still being valid and on OCSP or CRL being reachable online at that moment.
B-T, proven time
In the file A timestamp token from a TSA over the signature value, as an unsigned attribute in the same CMS. Shows the signature existed before the certificate expired or was revoked. Validation still needs online revocation data. Normally done at signing time; if it was missed, a document timestamp as a later update also satisfies B-T.
B-LT, validation data in the file
In the file A new incremental update with a /DSS dictionary in the catalog holding the certificates of the signer's chain and the TSA's chain, the matching OCSP responses or CRLs, and a /VRI entry per signature. Fetch the revocation data after the timestamp, so it postdates the signature. The file can now be validated offline; it no longer matters whether the CA's endpoints still exist.
Certificates alone do not make B-LT. A DSS with only /Certs is the common miss: nothing in the structure looks broken, the validator reports B-T, and Acrobat does not show "LTV enabled". Look in the object tree of the analyser: the /DSS must carry /OCSPs or /CRLs and a /VRI per signature, not just certificates.
B-LTA, the archive timestamp
In the file A final incremental update with an invisible /Sig field whose signature dictionary has /Type /DocTimeStamp and /SubFilter /ETSI.RFC3161, and whose ByteRange covers the whole file. Protects the signature and the validation data against algorithms weakening. Optionally followed by another DSS update and document timestamp to carry the TSA's own validation data. Renewable without limit: before the TSA certificate expires or the hash algorithm weakens, repeat this step.
A document timestamp on an incomplete DSS seals B-T, not B-LTA. The level is set by the weakest rung below it, so check the DSS before you count the timestamps. Files reach us in exactly this state.
Room to reserve: the archive timestamp is a new signature field with its own /Contents, holding a TimeStampToken and the TSA's chain, so 4 to 8 kB, and every renewal adds another field. Nothing is added to the original signature's /Contents, so the number you chose at step 0.5 does not have to grow for LTA.
What changes in your code
- B-T: give the library a timestamp source at complete. DSS:
setTspSourceon both services and levelPAdES_BASELINE_T. pyHanko: atimestamperonPdfSigner. Reserve more space in/Contentsat prepare; the token goes inside the CMS. That source can be ours: Timestamping has the hosts, the authentication and the policy, and any RFC 3161 client speaks it. - B-LT: an extension step that fetches OCSP or CRL for every certificate in the chain and the timestamp chain, and writes them into
/DSSwith/VRIin a new revision. DSS:PAdESService.extendDocumentwith online revocation sources on the verifier. pyHanko: a validation context that fetches, then the LTV update. - B-LTA: a document timestamp as the final revision, from the same timestamp source, and a renewal process that adds a fresh one before the previous timestamp's certificate expires. This is an operational commitment, not a one-time call.
Several signers
First all signatures, each with its own B-T, then one LT plus LTA pass for the whole. Taking each signature to LTA separately costs at least two extra revisions per signer and only pays off when a lot of time passes between signers.
What breaks it
One disallowed change after the first signature (a field value, the /NeedAppearances flag, a rewritten file) makes that signature suspect and every timestamp that follows it. Hence: everything in step 0 before the first signature, and append-only after it.
Coming in the next edition
- A worked B-LTA path with DSS, including the choice of TSA and the revocation sources.
- The same with pyHanko.
- A runnable sandbox: a container with the reference implementation pointed at the acceptance environment, so an integrator can see a correct file before writing a line.
- CAdES for non-PDF files, where the signed hash is the same and only the container differs.