问题
I'm generating a PDF document with signature and I want it to be LTV enabled. For this, I sign the PDF when creating it and then I add the second version containing the DSS with the validation related informations (VRI). As I found in some articles, I need to add the Certificate chain (without the root certificate - Authority) and the Certificate Revocation List (CRL). In my case, both will have 2 elements. After that I add the entry for the VRI which is a SHA-1 hash of the signature content (found in the first PDF verion in the /Contents ) with the value which refers the Certificates and CRL mentioned above.
For both the certificates and the revocation list elements I use the raw bytes stream of the content.
Here is my PDF sample
Edit
The way I obtain the CRL information is uising WynCrypt like this:
//Retrieve chained certificate
if(!CertGetCertificateChain(hChainEngine, pSignerCert, pTime, hAdditionalStore, &chainPara, dwFlags, NULL, &ppChainContext))
return NULL;
//first cert in chain is the end cert; last one is the root cert
for(int i = 0; i < ppChainContext->cChain; ++i)
{
PCERT_SIMPLE_CHAIN simpleChain = ppChainContext->rgpChain[i];
for(int j = 0; j < (int)simpleChain->cElement - 1; j++)//do not include root certificate
{
PCERT_CHAIN_ELEMENT chainElement = simpleChain->rgpElement[j];
if(chainElement->pCertContext)
{
//the certificate bytes
byte* certBytes =chainElement->pCertContext->pbCertEncoded
}
if(chainElement->pRevocationInfo && chainElement->pRevocationInfo->pCrlInfo)
{
PCCRL_CONTEXT crlContext = chainElement->pRevocationInfo->pCrlInfo->pBaseCrlContext;//get revocation context
//the bytes that will be written in PDF
byte* crlBytes = crlContext->pbCrlEncoded;
}
}
}
回答1:
Just had a quick look and objects 15 and 16 are OCSP responses but you are adding them as CRLs:
Stream Object 15
Stream Object 16
This ASN.1 Decoder is very handy!
In my source viewer the DSS dictionary (Object 21) is:
<<
/CRLs 19 0 R
/Certs 20 0 R
/VRI 18 0 R
>>
19 points to the Array atom:
[15 0 R 16 0 R]
Again VRI is not necessary for LTV it is currently basically an optimisation (see Appendix A1 in ETSI TS 102 778-4 which is basically taken from the PDF 2.0 specification). If you use it and add a timestamp (/TS entry) Adobe does not currently even display it correctly. In the VRI the TU/TS is also entirely optional and does not affect LTV validity (ibid).
回答2:
The term "LTV enabled"
As far as I know, there is no formal specification of the meaning of the term "LTV enabled". There are some non-normative descriptions thereof, in particular:
Leonard Rosenthol (PDF Architect & Principal Scientist at Adobe) once characterized it as
LTV enabled means that all information necessary to validate the file (minus root certs) is contained within.
(iText mailing list on Jan 10, 2013)
Another Adobe employee, Steven.Madwin, describes the implementation as
As part of the validation process [Acrobat] figures out if it has to go online to download revocation information, or, is all of the revocation information embedded in the PDF file. At this point it knows what it's going to say in the Signature Navigation Panel. If it had to download data then the signature is not LTV enabled, but if all of the revocation collateral is in the file then the signature is LTV enabled.
(Adobe support forums on Sep 24, 2013)
Thus, the meaning of the term "LTV enabled" depends on implementation details of the signature validation algorithms of Adobe Acrobat (which are closed source and not necessarily fixed) and on the underlying configurations. You can read me ranting about this in multiple older stack overflow answers...
Nonetheless, the mechanisms underneath these implementation details are not completely arbitrary, they essentially form a profile (albeit a proprietary, closed, and probably even changing one) of the existing published specifications on this topic, in particular RFCs.
In particular it is fairly clear what you should do for a good chance to have your signature marked "LTV enabled", add all information that a validator may possibly need in the validation process, in particular
- Add all intermediary certificates from the signer certificate to a certificate trusted by Adobe. If you are not sure which certificates are trusted, add all certificates up to the root certificate. If you know any of those certificates to be cross-signed by another CA, add the certificates of all those possible chains.
- For all those certificates (except root certificates) retrieve revocation information (CRLs or OCSP responses) and add them, too.
- For each added CRL and OCSP response determine its respective signer certificate, add that certificate and the certificates in its chain to the document to, retrieve and add revocation information for them (unless they are root certificates, or certificates with the
id-pkix-ocsp-nocheck
extension, or you already have revocation information for them) and so forth.
One challenge remains, though, and that is determining how exactly to add all those information to your PDF.
If you know the signer certificate before signing, you can add all the certificates to the certificate store in the signature container to create and all the revocation data to the signed adbe-revocationInfoArchival
attribute of the SignerInfo
therein.
If you don't, you can put those certificates and revocation information into the PAdES document security store (DSS), i.e. into special structures in an incremental update of the signed PDF. This DSS is not yet defined in ISO 32000-1; it has originally been defined in ETSI technical specifications (ETSI TS 102 778-4) and later norms (ETSI EN 319 142-1), and it has been adopted into the current PDF specification ISO 32000-2.
Why your PDF signature is not LTV enabled
Your PDF uses the DSS to store the certificates and revocation information but there are shortcoming in it.
As already explained by Peter G in his answer, your PDF's DSS in the CRLs and CRL arrays does not contain actual CRLs.
The objects in there are not simply OCSP responses either as Peter G said but instead OCSP responses wrapped into some other structure. The actual OCSP response in those objects starts at offset 160...
I would guess your code in that crlContext->pbCrlEncoded
buffer contains some wrapper for arbitrary revocation information and you must first parse it to see which type it actually is and then unwrap that actual revocation information object and embed it according to its type. I don't know WynCrypt, so this is pure guesswork...
Optional elements in the DSS
Two years ago I built a LTV-enabler, too. Back then experiments suggested that Adobe Acrobat requires certain DSS elements which are specified as optional, at least under certain circumstances: I LTV-enabled a PDF using Adobe Acrobat and reduced that PDF step-by-step towards something I built. It turned out that the VRI DSS subsection and the TU entries therein were necessary, removing either made the file not LTV-enabled.
I now used my that LTV-enabler (actually a variant that can be given extra certificates) to LTV-enable your PDF. This worked. Out of interest I also reduced this LTV-enabled PDF. Interestingly, I could remove TU and even VRI without losing the LTV-enabled status.
Thus, either Adobe Acrobat has changed to not require those elements in general anymore or the file I started with in my former experiments was a somewhat special case requiring extra data while they are not required in other cases.
来源:https://stackoverflow.com/questions/60413766/cant-figure-out-why-my-pdf-signature-is-not-ltv-enabled