1

I'm using this to sign a PDF document, as the related question captures my scenario. However, I'm unable to generate the LTV (I'm using this as a guide) because I'm not able to instantiate valid OscpClient and CrlClient objects to use in the addLtv function. I'm using iTextSharp 5.5.10.

Is there some documentation that can point to the right direction?

Here is what I have at the moment:

try {
    // Getting the certificate 
    X509Store store = new X509Store("MY", StoreLocation.CurrentUser);
    store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
    X509Certificate2 x509 = selectCert(store.Certificates, "<<some descriptor>>");

    // Initialise the various objects
    PdfReader pdfReader = new PdfReader("<<path to source file>>");
    FileStream signedPdf = new FileStream("<<path to dest file>>", FileMode.Create);

    PdfStamper pdfStamper = PdfStamper.CreateSignature(pdfReader, signedPdf, '\0', null, true);
    pdfStamper.MoreInfo = pdfReader.Info;

    PdfSignatureAppearance signatureAppearance = pdfStamper.SignatureAppearance;
    X509Certificate2Signature externalSignature = new X509Certificate2Signature(x509, "SHA-256");

    Org.BouncyCastle.X509.X509CertificateParser cp = new Org.BouncyCastle.X509.X509CertificateParser();
    Org.BouncyCastle.X509.X509Certificate[] chain = new Org.BouncyCastle.X509.X509Certificate[] {
        cp.ReadCertificate(x509.RawData)
    };

    // Initialise the IOcspClient implementor
    // https://itextsupport.com/apidocs/itext5/latest/com/itextpdf/text/pdf/security/OcspClientBouncyCastle.html
    OcspClientBouncyCastle ocsp = new OcspClientBouncyCastle(
        // The first point that I get stuck on the documentation
        new OCSPVerifier()
    );

    // Initialise the ICrlClient implementor
    // https://itextsupport.com/apidocs/itext5/latest/com/itextpdf/text/pdf/security/CrlClientOnline.html
    CrlClientOnline crl = new CrlClientOnline(
        // https://stackoverflow.com/a/40894818
        GetCrlDistributionPointURI(x509)
    );

    List<String> names = pdfStamper.AcroFields.GetSignatureNames();
    String sigName = names[names.Capacity - 1];
    PdfPKCS7 pkcs7 = pdfStamper.AcroFields.VerifySignature(sigName);

    // The long term validation
    if (pkcs7.IsTsp) {
        pdfStamper.LtvVerification.AddVerification(
            sigName, ocsp, crl,
            LtvVerification.CertificateOption.SIGNING_CERTIFICATE,
            LtvVerification.Level.OCSP_CRL,
            LtvVerification.CertificateInclusion.NO
        );
    }
    else {
        foreach (String name in names) {
            pdfStamper.LtvVerification.AddVerification(
                name, ocsp, crl,
                LtvVerification.CertificateOption.WHOLE_CHAIN,
                LtvVerification.Level.OCSP_CRL,
                LtvVerification.CertificateInclusion.NO
            );
        }
    }

    // Sign the doc and 
    MakeSignature.SignDetached(signatureAppearance, externalSignature, chain, null, null, null, 0, CryptoStandard.CMS);
    pdfStamper.Close();
    return "Done";
}

catch (Exception ex) {
    return ex.Message;
}
Sand
  • 113
  • 2
  • 6
  • *"I'm not able to instantiate valid OscpClient and CrlClient objects to use in the addLtv function"* - what have you tried? In which way were you not able to? – mkl Oct 09 '18 at 21:42
  • I've updated my question with what I have at the moment. Hope this helps. – Sand Oct 10 '18 at 16:57

1 Answers1

1

The OCSP client

// Initialise the IOcspClient implementor
// https://itextsupport.com/apidocs/itext5/latest/com/itextpdf/text/pdf/security/OcspClientBouncyCastle.html
OcspClientBouncyCastle ocsp = new OcspClientBouncyCastle(
    // The first point that I get stuck on the documentation
    new OCSPVerifier()
);

First of all, you only need an OcspVerifier instance if you want to verify the OCSP responses. As your task is to generate a signature with LTV information, you can skip this verification if you are sure your program won't have to deal with a compromised CA PKI infrastructure. I.e. you can do

OcspClientBouncyCastle ocsp = new OcspClientBouncyCastle(null);

(or even

OcspClientBouncyCastle ocsp = new OcspClientBouncyCastle();

if the obsolete tag does not disturb you).

Otherwise, if you really want to verify the OCSP responses, the OCSPVerifier constructor has two parameters:

/**
 * Creates an OCSPVerifier instance.
 * @param verifier  the next verifier in the chain
 * @param ocsps a list of OCSP responses
 */
public OcspVerifier(CertificateVerifier verifier, List<BasicOcspResp> ocsps)

As you do neither have any idea about basing your OCSP response validation on some CertificateVerifier nor have a list of prepared OCSP responses, have you tried yet to simply use

OcspClientBouncyCastle ocsp = new OcspClientBouncyCastle(
    new OCSPVerifier(null, null)
);

The CRL client

// Initialise the ICrlClient implementor
// https://itextsupport.com/apidocs/itext5/latest/com/itextpdf/text/pdf/security/CrlClientOnline.html
CrlClientOnline crl = new CrlClientOnline(
    // https://stackoverflow.com/a/40894818
    GetCrlDistributionPointURI(x509)
);

If your code fails (which I cannot check because you don't explain that GetCrlDistributionPointURI method): Have you tried using the default constructor yet:

CrlClientOnline crl = new CrlClientOnline();

Depending on your PKI this might be all you need...

LTV enabling

It is not clear from your question which LTV information you want to add to your PDF. As you don't mention PAdES, I assume you want to add the information for Adobe's proprietary "LTV enabled" check.

In that case you might simply want to try the AdobeLtvEnabling class from this answer to the question "I want to sign a pdf document with ITextSharp and return ltv pdf enabled file".

mkl
  • 90,588
  • 15
  • 125
  • 265