Digital signatures - chapter 5

This is a code example of iText PDF, discover more.

1st November 2015
admin-marketing

Switch code for this example

C5_01_SignatureIntegrity.java
package signatures.chapter5;

import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.Security;
import java.util.ArrayList;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

import com.itextpdf.text.log.LoggerFactory;
import com.itextpdf.text.log.SysoLogger;
import com.itextpdf.text.pdf.AcroFields;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.security.PdfPKCS7;

public class C5_01_SignatureIntegrity {
	public static final String EXAMPLE1 = "results/chapter2/hello_level_1_annotated_wrong.pdf";
	public static final String EXAMPLE2 = "results/chapter2/step_4_signed_by_alice_bob_carol_and_dave.pdf";
	public static final String EXAMPLE3 = "results/chapter2/step_6_signed_by_dave_broken_by_chuck.pdf";

	public PdfPKCS7 verifySignature(AcroFields fields, String name) throws GeneralSecurityException, IOException {
		System.out.println("Signature covers whole document: " + fields.signatureCoversWholeDocument(name));
		System.out.println("Document revision: " + fields.getRevision(name) + " of " + fields.getTotalRevisions());
        PdfPKCS7 pkcs7 = fields.verifySignature(name);
        System.out.println("Integrity check OK? " + pkcs7.verify());
        return pkcs7;
	}
	
	public void verifySignatures(String path) throws IOException, GeneralSecurityException {
		System.out.println(path);
        PdfReader reader = new PdfReader(path);
        AcroFields fields = reader.getAcroFields();
        ArrayList names = fields.getSignatureNames();
		for (String name : names) {
			System.out.println("===== " + name + " =====");
			verifySignature(fields, name);
		}
		System.out.println();
	}
	
	public static void main(String[] args) throws IOException, GeneralSecurityException {
		LoggerFactory.getInstance().setLogger(new SysoLogger());
		BouncyCastleProvider provider = new BouncyCastleProvider();
		Security.addProvider(provider);
		C5_01_SignatureIntegrity app = new C5_01_SignatureIntegrity();
		app.verifySignatures(EXAMPLE1);
		app.verifySignatures(EXAMPLE2);
		app.verifySignatures(EXAMPLE3);
	}
}
C5_02_SignatureInfo.java
package signatures.chapter5;

import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.Security;
import java.security.cert.X509Certificate;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.tsp.TimeStampToken;

import com.itextpdf.text.Rectangle;
import com.itextpdf.text.log.LoggerFactory;
import com.itextpdf.text.log.SysoLogger;
import com.itextpdf.text.pdf.AcroFields;
import com.itextpdf.text.pdf.AcroFields.FieldPosition;
import com.itextpdf.text.pdf.PdfDictionary;
import com.itextpdf.text.pdf.PdfName;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfString;
import com.itextpdf.text.pdf.security.CertificateInfo;
import com.itextpdf.text.pdf.security.PdfPKCS7;
import com.itextpdf.text.pdf.security.SignaturePermissions;
import com.itextpdf.text.pdf.security.SignaturePermissions.FieldLock;

public class C5_02_SignatureInfo extends C5_01_SignatureIntegrity {
	public static final String EXAMPLE1 = "results/chapter2/step_4_signed_by_alice_bob_carol_and_dave.pdf";
	public static final String EXAMPLE2 = "results/chapter3/hello_cacert_ocsp_ts.pdf";
	public static final String EXAMPLE3 = "results/chapter3/hello_token.pdf";
	public static final String EXAMPLE4 = "results/chapter2/hello_signed4.pdf";
	public static final String EXAMPLE5 = "results/chapter4/hello_smartcard_Signature.pdf";
	public static final String EXAMPLE6 = "results/chapter2/field_metadata.pdf";

	public SignaturePermissions inspectSignature(AcroFields fields, String name, SignaturePermissions perms) throws GeneralSecurityException, IOException {
		List fps = fields.getFieldPositions(name);
		if (fps != null && fps.size() > 0) {
			FieldPosition fp = fps.get(0);
			Rectangle pos = fp.position;
			if (pos.getWidth() == 0 || pos.getHeight() == 0) {
				System.out.println("Invisible signature");
			}
			else {
				System.out.println(String.format("Field on page %s; llx: %s, lly: %s, urx: %s; ury: %s",
					fp.page, pos.getLeft(), pos.getBottom(), pos.getRight(), pos.getTop()));
			}
		}
		
		PdfPKCS7 pkcs7 = super.verifySignature(fields, name);
		System.out.println("Digest algorithm: " + pkcs7.getHashAlgorithm());
		System.out.println("Encryption algorithm: " + pkcs7.getEncryptionAlgorithm());
		System.out.println("Filter subtype: " + pkcs7.getFilterSubtype());
		X509Certificate cert = (X509Certificate) pkcs7.getSigningCertificate();
			System.out.println("Name of the signer: " + CertificateInfo.getSubjectFields(cert).getField("CN"));
		if (pkcs7.getSignName() != null)
			System.out.println("Alternative name of the signer: " + pkcs7.getSignName());
		SimpleDateFormat date_format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SS");
		System.out.println("Signed on: " + date_format.format(pkcs7.getSignDate().getTime()));
		if (pkcs7.getTimeStampDate() != null) {
			System.out.println("TimeStamp: " + date_format.format(pkcs7.getTimeStampDate().getTime()));
			TimeStampToken ts = pkcs7.getTimeStampToken();
			System.out.println("TimeStamp service: " + ts.getTimeStampInfo().getTsa());
			System.out.println("Timestamp verified? " + pkcs7.verifyTimestampImprint());
		}
		System.out.println("Location: " + pkcs7.getLocation());
		System.out.println("Reason: " + pkcs7.getReason());
		PdfDictionary sigDict = fields.getSignatureDictionary(name);
		PdfString contact = sigDict.getAsString(PdfName.CONTACTINFO);
		if (contact != null)
			System.out.println("Contact info: " + contact);
		perms = new SignaturePermissions(sigDict, perms);
		System.out.println("Signature type: " + (perms.isCertification() ? "certification" : "approval"));
		System.out.println("Filling out fields allowed: " + perms.isFillInAllowed());
		System.out.println("Adding annotations allowed: " + perms.isAnnotationsAllowed());
		for (FieldLock lock : perms.getFieldLocks()) {
			System.out.println("Lock: " + lock.toString());
		}
        return perms;
	}
	
	public void inspectSignatures(String path) throws IOException, GeneralSecurityException {
		System.out.println(path);
        PdfReader reader = new PdfReader(path);
        AcroFields fields = reader.getAcroFields();
        ArrayList names = fields.getSignatureNames();
        SignaturePermissions perms = null;
		for (String name : names) {
			System.out.println("===== " + name + " =====");
			perms = inspectSignature(fields, name, perms);
		}
		System.out.println();
	}
	
	public static void main(String[] args) throws IOException, GeneralSecurityException {
		LoggerFactory.getInstance().setLogger(new SysoLogger());
		BouncyCastleProvider provider = new BouncyCastleProvider();
		Security.addProvider(provider);
		C5_02_SignatureInfo app = new C5_02_SignatureInfo();
		app.inspectSignatures(EXAMPLE1);
		app.inspectSignatures(EXAMPLE2);
		app.inspectSignatures(EXAMPLE3);
		app.inspectSignatures(EXAMPLE4);
		app.inspectSignatures(EXAMPLE5);
		app.inspectSignatures(EXAMPLE6);
	}
}
C5_03_CertificateValidation.java
package signatures.chapter5;

import java.io.FileInputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.Security;
import java.security.cert.CRL;
import java.security.cert.Certificate;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateFactory;
import java.security.cert.CertificateNotYetValidException;
import java.security.cert.X509CRL;
import java.security.cert.X509Certificate;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.bouncycastle.cert.ocsp.BasicOCSPResp;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import com.itextpdf.text.log.LoggerFactory;
import com.itextpdf.text.log.SysoLogger;
import com.itextpdf.text.pdf.AcroFields;
import com.itextpdf.text.pdf.security.CRLVerifier;
import com.itextpdf.text.pdf.security.CertificateVerification;
import com.itextpdf.text.pdf.security.OCSPVerifier;
import com.itextpdf.text.pdf.security.PdfPKCS7;
import com.itextpdf.text.pdf.security.VerificationException;
import com.itextpdf.text.pdf.security.VerificationOK;

public class C5_03_CertificateValidation extends C5_01_SignatureIntegrity {
	public static final String ADOBE = "src/main/resources/adobeRootCA.cer";
	public static final String CACERT = "src/main/resources/CACertSigningAuthority.crt";
	public static final String BRUNO = "src/main/resources/bruno.crt";

	public static final String EXAMPLE1 = "results/chapter3/hello_cacert_ocsp_ts.pdf";
	public static final String EXAMPLE2 = "results/chapter3/hello_token.pdf";
	public static final String EXAMPLE3 = "results/chapter2/hello_signed1.pdf";
	public static final String EXAMPLE4 = "results/chapter4/hello_smartcard_Signature.pdf";

	KeyStore ks;

	public PdfPKCS7 verifySignature(AcroFields fields, String name)
			throws GeneralSecurityException, IOException {
		PdfPKCS7 pkcs7 = super.verifySignature(fields, name);
		Certificate[] certs = pkcs7.getSignCertificateChain();
		Calendar cal = pkcs7.getSignDate();
		List errors = CertificateVerification.verifyCertificates(certs, ks, cal);
		if (errors.size() == 0)
			System.out.println("Certificates verified against the KeyStore");
		else
			System.out.println(errors);
		for (int i = 0; i < certs.length; i++) {
			X509Certificate cert = (X509Certificate) certs[i];
			System.out.println("=== Certificate " + i + " ===");
			showCertificateInfo(cert, cal.getTime());
		}
		X509Certificate signCert = (X509Certificate)certs[0];
		X509Certificate issuerCert = (certs.length > 1 ? (X509Certificate)certs[1] : null);
		System.out.println("=== Checking validity of the document at the time of signing ===");
		checkRevocation(pkcs7, signCert, issuerCert, cal.getTime());
		System.out.println("=== Checking validity of the document today ===");
		checkRevocation(pkcs7, signCert, issuerCert, new Date());
		return pkcs7;
	}
	
	public static void checkRevocation(PdfPKCS7 pkcs7, X509Certificate signCert, X509Certificate issuerCert, Date date) throws GeneralSecurityException, IOException {
		List ocsps = new ArrayList();
		if (pkcs7.getOcsp() != null)
			ocsps.add(pkcs7.getOcsp());
		OCSPVerifier ocspVerifier = new OCSPVerifier(null, ocsps);
		List verification =
			ocspVerifier.verify(signCert, issuerCert, date);
		if (verification.size() == 0) {
			List crls = new ArrayList();
			if (pkcs7.getCRLs() != null) {
				for (CRL crl : pkcs7.getCRLs())
					crls.add((X509CRL)crl);
			}
			CRLVerifier crlVerifier = new CRLVerifier(null, crls);
			verification.addAll(crlVerifier.verify(signCert, issuerCert, date));
		}
		if (verification.size() == 0) {
			System.out.println("The signing certificate couldn't be verified");
		}
		else {
			for (VerificationOK v : verification)
				System.out.println(v);
		}
	}

	public void showCertificateInfo(X509Certificate cert, Date signDate) {
		System.out.println("Issuer: " + cert.getIssuerDN());
		System.out.println("Subject: " + cert.getSubjectDN());
		SimpleDateFormat date_format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SS");
		System.out.println("Valid from: " + date_format.format(cert.getNotBefore()));
		System.out.println("Valid to: " + date_format.format(cert.getNotAfter()));
		try {
			cert.checkValidity(signDate);
			System.out
					.println("The certificate was valid at the time of signing.");
		} catch (CertificateExpiredException e) {
			System.out
					.println("The certificate was expired at the time of signing.");
		} catch (CertificateNotYetValidException e) {
			System.out
					.println("The certificate wasn't valid yet at the time of signing.");
		}
		try {
			cert.checkValidity();
			System.out.println("The certificate is still valid.");
		} catch (CertificateExpiredException e) {
			System.out.println("The certificate has expired.");
		} catch (CertificateNotYetValidException e) {
			System.out.println("The certificate isn't valid yet.");
		}
	}
	
	private void setKeyStore(KeyStore ks) {
		this.ks = ks;
	}

	public static void main(String[] args) throws IOException,
			GeneralSecurityException {
		LoggerFactory.getInstance().setLogger(new SysoLogger());
		BouncyCastleProvider provider = new BouncyCastleProvider();
		Security.addProvider(provider);
		C5_03_CertificateValidation app = new C5_03_CertificateValidation();
		KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());

		ks.load(null, null);
		CertificateFactory cf = CertificateFactory.getInstance("X.509");
		ks.setCertificateEntry("adobe",
				cf.generateCertificate(new FileInputStream(ADOBE)));
		ks.setCertificateEntry("cacert",
				cf.generateCertificate(new FileInputStream(CACERT)));
		ks.setCertificateEntry("bruno",
				cf.generateCertificate(new FileInputStream(BRUNO)));
		app.setKeyStore(ks);
		app.verifySignatures(EXAMPLE1);
		app.verifySignatures(EXAMPLE2);
		app.verifySignatures(EXAMPLE3);
		app.verifySignatures(EXAMPLE4);
	}
}
C5_04_LTV.java
package signatures.chapter5;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.Security;
import java.util.List;
import java.util.Properties;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

import com.itextpdf.text.DocumentException;
import com.itextpdf.text.log.LoggerFactory;
import com.itextpdf.text.log.SysoLogger;
import com.itextpdf.text.pdf.AcroFields;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfSignatureAppearance;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.security.CrlClient;
import com.itextpdf.text.pdf.security.CrlClientOnline;
import com.itextpdf.text.pdf.security.LtvTimestamp;
import com.itextpdf.text.pdf.security.LtvVerification;
import com.itextpdf.text.pdf.security.OcspClient;
import com.itextpdf.text.pdf.security.OcspClientBouncyCastle;
import com.itextpdf.text.pdf.security.PdfPKCS7;
import com.itextpdf.text.pdf.security.TSAClient;
import com.itextpdf.text.pdf.security.TSAClientBouncyCastle;

public class C5_04_LTV {

	public static final String EXAMPLE1 = "results/chapter3/hello_token.pdf";
	public static final String EXAMPLE2 = "results/chapter4/hello_smartcard_Signature.pdf";
	public static final String EXAMPLE3 = "results/chapter3/hello_cacert_ocsp_ts.pdf";
	public static final String DEST = "results/chapter5/ltv_%s.pdf";
	
	public static void main(String[] args) throws IOException, DocumentException, GeneralSecurityException {
		Security.addProvider(new BouncyCastleProvider());
        LoggerFactory.getInstance().setLogger(new SysoLogger());
		Properties properties = new Properties();
		properties.load(new FileInputStream("c:/home/blowagie/key.properties"));
        String tsaUrl = properties.getProperty("TSAURL");
        String tsaUser = properties.getProperty("TSAUSERNAME");
        String tsaPass = properties.getProperty("TSAPASSWORD");
        C5_04_LTV app = new C5_04_LTV();
        TSAClient tsa = new TSAClientBouncyCastle(tsaUrl, tsaUser, tsaPass, 6500, "SHA512");
        OcspClient ocsp = new OcspClientBouncyCastle();
        app.addLtv(EXAMPLE1, String.format(DEST, 1), ocsp, new CrlClientOnline(), tsa);
        System.out.println();
        app.addLtv(EXAMPLE2, String.format(DEST, 2), ocsp, new CrlClientOnline(), tsa);
        System.out.println();
        app.addLtv(EXAMPLE3, String.format(DEST, 3), ocsp, new CrlClientOnline(), tsa);
        System.out.println();
        app.addLtv(String.format(DEST, 1), String.format(DEST, 4), null, new CrlClientOnline(), tsa);
	}
	
	public void addLtv(String src, String dest, OcspClient ocsp, CrlClient crl, TSAClient tsa) throws IOException, DocumentException, GeneralSecurityException {
        PdfReader r = new PdfReader(src);
        FileOutputStream fos = new FileOutputStream(dest);
        PdfStamper stp = PdfStamper.createSignature(r, fos, '\0', null, true);
        LtvVerification v = stp.getLtvVerification();
        AcroFields fields = stp.getAcroFields();
		List names = fields.getSignatureNames();
        String sigName = names.get(names.size() - 1);
		PdfPKCS7 pkcs7 = fields.verifySignature(sigName);
		if (pkcs7.isTsp())
			System.out.println("TIMESTAMP!");
		for (String name : names) {
			v.addVerification(name, ocsp, crl, LtvVerification.CertificateOption.WHOLE_CHAIN, LtvVerification.Level.OCSP_CRL, LtvVerification.CertificateInclusion.NO);
        }
        PdfSignatureAppearance sap = stp.getSignatureAppearance();
        LtvTimestamp.timestamp(sap, tsa, null); 
	}
}
C5_05_CheckLTV.java
package signatures.chapter5;

import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.Security;
import java.security.cert.X509Certificate;
import java.util.ArrayList;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

import com.itextpdf.text.log.LoggerFactory;
import com.itextpdf.text.log.SysoLogger;
import com.itextpdf.text.pdf.AcroFields;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.security.CertificateInfo;
import com.itextpdf.text.pdf.security.PdfPKCS7;

public class C5_05_CheckLTV {
	public static final String EXAMPLE1 = "results/chapter5/ltv_1.pdf";
	public static final String EXAMPLE2 = "results/chapter5/ltv_2.pdf";
	public static final String EXAMPLE3 = "results/chapter5/ltv_3.pdf";
	public static final String EXAMPLE4 = "results/chapter5/ltv_4.pdf";

	public PdfPKCS7 verifySignature(AcroFields fields, String name) throws GeneralSecurityException, IOException {
		System.out.println("Signature covers whole document: " + fields.signatureCoversWholeDocument(name));
		System.out.println("Document revision: " + fields.getRevision(name) + " of " + fields.getTotalRevisions());
        PdfPKCS7 pkcs7 = fields.verifySignature(name);
        System.out.println("Integrity check OK? " + pkcs7.verify());
		System.out.println("Digest algorithm: " + pkcs7.getHashAlgorithm());
		System.out.println("Encryption algorithm: " + pkcs7.getEncryptionAlgorithm());
		System.out.println("Filter subtype: " + pkcs7.getFilterSubtype());
		X509Certificate cert = (X509Certificate) pkcs7.getSigningCertificate();
		System.out.println("Name of the signer: " + CertificateInfo.getSubjectFields(cert).getField("CN"));
        return pkcs7;
	}
	
	public void verifySignatures(String path) throws IOException, GeneralSecurityException {
		System.out.println(path);
        PdfReader reader = new PdfReader(path);
        AcroFields fields = reader.getAcroFields();
        ArrayList names = fields.getSignatureNames();
		for (String name : names) {
			System.out.println("===== " + name + " =====");
			verifySignature(fields, name);
		}
		System.out.println();
	}
	
	public static void main(String[] args) throws IOException, GeneralSecurityException {
		LoggerFactory.getInstance().setLogger(new SysoLogger());
		BouncyCastleProvider provider = new BouncyCastleProvider();
		Security.addProvider(provider);
		C5_05_CheckLTV app = new C5_05_CheckLTV();
		app.verifySignatures(EXAMPLE1);
		app.verifySignatures(EXAMPLE2);
		app.verifySignatures(EXAMPLE3);
		app.verifySignatures(EXAMPLE4);
	}
}
C5_06_ValidateLTV.java
package signatures.chapter5;

import java.io.FileInputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.Security;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.security.CertificateVerifier;
import com.itextpdf.text.pdf.security.LtvVerifier;
import com.itextpdf.text.pdf.security.LtvVerification.CertificateOption;
import com.itextpdf.text.pdf.security.VerificationOK;

public class C5_06_ValidateLTV {
	public static final String ADOBE = "src/main/resources/adobeRootCA.cer";
	public static final String EXAMPLE1 = "results/chapter5/ltv_1.pdf";
	public static final String EXAMPLE2 = "results/chapter5/ltv_2.pdf";
	public static final String EXAMPLE3 = "results/chapter5/ltv_3.pdf";
	public static final String EXAMPLE4 = "results/chapter5/ltv_4.pdf";
	
	public static void main(String[] args) throws IOException, GeneralSecurityException {
		BouncyCastleProvider provider = new BouncyCastleProvider();
		Security.addProvider(provider);
		C5_06_ValidateLTV app = new C5_06_ValidateLTV();
		System.out.println(EXAMPLE1);
		app.validate(new PdfReader(EXAMPLE1));
		System.out.println();
		System.out.println(EXAMPLE2);
		app.validate(new PdfReader(EXAMPLE2));
		System.out.println();
		System.out.println(EXAMPLE3);
		app.validate(new PdfReader(EXAMPLE3));
		System.out.println();
		System.out.println(EXAMPLE4);
		app.validate(new PdfReader(EXAMPLE4));
	}
	
	public void validate(PdfReader reader) throws IOException, GeneralSecurityException {
		KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
		ks.load(null, null);
		CertificateFactory cf = CertificateFactory.getInstance("X.509");
		ks.setCertificateEntry("adobe",
				cf.generateCertificate(new FileInputStream(ADOBE)));
		
		CertificateVerifier custom = new CertificateVerifier(null) {
			public List verify(X509Certificate signCert,
					X509Certificate issuerCert, Date signDate)
					throws GeneralSecurityException, IOException {
				System.out.println(signCert.getSubjectDN().getName() + ": ALL VERIFICATIONS DONE");
				return new ArrayList();
			}
		};
		
 		LtvVerifier data = new LtvVerifier(reader);
 		data.setRootStore(ks);
 		data.setCertificateOption(CertificateOption.WHOLE_CHAIN);
 		data.setVerifier(custom);
 		data.setOnlineCheckingAllowed(false);
 		data.setVerifyRootCertificate(false);
 		List list = new ArrayList();
 		try {
 			data.verify(list);
 		}
 		catch(GeneralSecurityException e) {
 			System.err.println(e.getMessage());
 		}
		System.out.println();
		if (list.size() == 0) {
			System.out.println("The document can't be verified");
		}
 		for (VerificationOK v : list)
 			System.out.println(v.toString());
	}
}
C5_01_SignatureIntegrity.cs
/*
 * This class is part of the white paper entitled
 * "Digital Signatures for PDF documents"
 * written by Bruno Lowagie
 * 
 * For more info, go to: http://itextpdf.com/learn
 */

using System;
using System.Collections.Generic;
using iTextSharp.text.log;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.security;

namespace signatures.chapter5 {
    public class C5_01_SignatureIntegrity {
        public const String EXAMPLE1 = "../../../../results/chapter2/hello_level_1_annotated_wrong.pdf";
	    public const String EXAMPLE2 = "../../../../results/chapter2/step_4_signed_by_alice_bob_carol_and_dave.pdf";
	    public const String EXAMPLE3 = "../../../../results/chapter2/step_6_signed_by_dave_broken_by_chuck.pdf";

	    virtual public PdfPKCS7 VerifySignature(AcroFields fields, String name) {
		    Console.WriteLine("Signature covers whole document: " + fields.SignatureCoversWholeDocument(name));
		    Console.WriteLine("Document revision: " + fields.GetRevision(name) + " of " + fields.TotalRevisions);
            PdfPKCS7 pkcs7 = fields.VerifySignature(name);
            Console.WriteLine("Integrity check OK? " + pkcs7.Verify());
            return pkcs7;
	    }
    	
	    public void VerifySignatures(String path) {
		    Console.WriteLine(path);
            PdfReader reader = new PdfReader(path);
            AcroFields fields = reader.AcroFields;
            List names = fields.GetSignatureNames();
	        foreach (string name in names) {
	            Console.WriteLine("===== " + name + " =====");
			    VerifySignature(fields, name);
	        }
	        Console.WriteLine();
	    }
    	
	    public static void Main(String[] args) {
		    LoggerFactory.GetInstance().SetLogger(new SysoLogger());
		    C5_01_SignatureIntegrity app = new C5_01_SignatureIntegrity();
		    app.VerifySignatures(EXAMPLE1);
		    app.VerifySignatures(EXAMPLE2);
		    app.VerifySignatures(EXAMPLE3);
	    }
    }
}
C5_02_SignatureInfo.cs
/*
 * This class is part of the white paper entitled
 * "Digital Signatures for PDF documents"
 * written by Bruno Lowagie
 * 
 * For more info, go to: http://itextpdf.com/learn
 */

using System;
using System.Collections.Generic;
using Org.BouncyCastle.Tsp;
using Org.BouncyCastle.X509;
using iTextSharp.text;
using iTextSharp.text.log;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.security;

namespace signatures.chapter5 {
    class C5_02_SignatureInfo : C5_01_SignatureIntegrity {
        public const String EXAMPLE1 = "../../../../results/chapter2/step_4_signed_by_alice_bob_carol_and_dave.pdf";
        public const String EXAMPLE2 = "../../../../results/chapter3/hello_cacert_ocsp_ts.pdf";
        public const String EXAMPLE3 = "../../../../results/chapter3/hello_token.pdf";
        public const String EXAMPLE4 = "../../../../results/chapter2/hello_signed4.pdf";
        public const String EXAMPLE5 = "../../../../results/chapter4/hello_smartcard_Signature.pdf";
        public const String EXAMPLE6 = "../../../../results/chapter2/field_metadata.pdf";

	    public SignaturePermissions InspectSignature(AcroFields fields, String name, SignaturePermissions perms) {
		    IList fps = fields.GetFieldPositions(name);
		    if (fps != null && fps.Count > 0) {
			    AcroFields.FieldPosition fp = fps[0];
			    Rectangle pos = fp.position;
			    if (pos.Width == 0 || pos.Height == 0) {
				    Console.WriteLine("Invisible signature");
			    }
			    else {
				    Console.WriteLine("Field on page {0}; llx: {1}, lly: {2}, urx: {3}; ury: {4}",
					    fp.page, pos.Left, pos.Bottom, pos.Right, pos.Top);
			    }
		    }
    		
		    PdfPKCS7 pkcs7 = VerifySignature(fields, name);
		    Console.WriteLine("Digest algorithm: " + pkcs7.GetHashAlgorithm());
		    Console.WriteLine("Encryption algorithm: " + pkcs7.GetEncryptionAlgorithm());
		    Console.WriteLine("Filter subtype: " + pkcs7.GetFilterSubtype());
		    X509Certificate cert = pkcs7.SigningCertificate;
			    Console.WriteLine("Name of the signer: " + CertificateInfo.GetSubjectFields(cert).GetField("CN"));
		    if (pkcs7.SignName != null)
			    Console.WriteLine("Alternative name of the signer: " + pkcs7.SignName);
		    
		    Console.WriteLine("Signed on: " + pkcs7.SignDate.ToString("yyyy-MM-dd HH:mm:ss.ff"));
            if (!pkcs7.TimeStampDate.Equals(DateTime.MaxValue)) {
			    Console.WriteLine("TimeStamp: " + pkcs7.TimeStampDate.ToString("yyyy-MM-dd HH:mm:ss.ff"));
			    TimeStampToken ts = pkcs7.TimeStampToken;
			    Console.WriteLine("TimeStamp service: " + ts.TimeStampInfo.Tsa);
			    Console.WriteLine("Timestamp verified? " + pkcs7.VerifyTimestampImprint());
		    }
		    Console.WriteLine("Location: " + pkcs7.Location);
		    Console.WriteLine("Reason: " + pkcs7.Reason);
		    PdfDictionary sigDict = fields.GetSignatureDictionary(name);
		    PdfString contact = sigDict.GetAsString(PdfName.CONTACTINFO);
		    if (contact != null)
			    Console.WriteLine("Contact info: " + contact);
		    perms = new SignaturePermissions(sigDict, perms);
		    Console.WriteLine("Signature type: " + (perms.Certification ? "certification" : "approval"));
		    Console.WriteLine("Filling out fields allowed: " + perms.FillInAllowed);
		    Console.WriteLine("Adding annotations allowed: " + perms.AnnotationsAllowed);
		    foreach (SignaturePermissions.FieldLock Lock in perms.FieldLocks) {
			    Console.WriteLine("Lock: " + Lock);
		    }
            return perms;
	    }
    	
	    public void InspectSignatures(String path) {
		    Console.WriteLine(path);
            PdfReader reader = new PdfReader(path);
            AcroFields fields = reader.AcroFields;
            List names = fields.GetSignatureNames();
            SignaturePermissions perms = null;
		    foreach (String name in names) {
			    Console.WriteLine("===== " + name + " =====");
			    perms = InspectSignature(fields, name, perms);
		    }
		    Console.WriteLine();
	    }
    	
	    static void Main(String[] args) {
		    LoggerFactory.GetInstance().SetLogger(new SysoLogger());
		    C5_02_SignatureInfo app = new C5_02_SignatureInfo();
		    app.InspectSignatures(EXAMPLE1);
		    app.InspectSignatures(EXAMPLE2);
		    app.InspectSignatures(EXAMPLE3);
		    app.InspectSignatures(EXAMPLE4);
		    app.InspectSignatures(EXAMPLE5);
		    app.InspectSignatures(EXAMPLE6);
	    }
    }
}
C5_03_CertificateValidation.cs
/*
 * This class is part of the white paper entitled
 * "Digital Signatures for PDF documents"
 * written by Bruno Lowagie
 * 
 * For more info, go to: http://itextpdf.com/learn
 */

using System;
using System.Collections.Generic;
using System.IO;
using Org.BouncyCastle.Ocsp;
using Org.BouncyCastle.Security.Certificates;
using Org.BouncyCastle.X509;
using iTextSharp.text.log;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.security;
using X509Certificate = Org.BouncyCastle.X509.X509Certificate;

namespace signatures.chapter5 {
    class C5_03_CertificateValidation : C5_01_SignatureIntegrity {
        public const String ADOBE = "../../../../resources/adobeRootCA.cer";
        public const String CACERT = "../../../../resources/CACertSigningAuthority.crt";
        public const String BRUNO = "../../../../resources/bruno.crt";

        public const String EXAMPLE1 = "../../../../results/chapter3/hello_cacert_ocsp_ts.pdf";
        public const String EXAMPLE2 = "../../../../results/chapter3/hello_token.pdf";
        public const String EXAMPLE3 = "../../../../results/chapter2/hello_signed1.pdf";
        public const String EXAMPLE4 = "../../../../results/chapter4/hello_smartcard_Signature.pdf";

        readonly private List certificates = new List();

	    override public PdfPKCS7 VerifySignature(AcroFields fields, String name) {
		    PdfPKCS7 pkcs7 = base.VerifySignature(fields, name);
		    X509Certificate[] certs = pkcs7.SignCertificateChain;
		    DateTime cal = pkcs7.SignDate;
            
		    Object[] errors = CertificateVerification.VerifyCertificates(certs, certificates, null, cal);
		    if (errors == null)
			    Console.WriteLine("Certificates verified against the KeyStore");
		    else
		        foreach (object error in errors)
		            Console.WriteLine(error);
		    for (int i = 0; i < certs.Length; ++i) {
			    X509Certificate cert = certs[i];
			    Console.WriteLine("=== Certificate " + i + " ===");
			    ShowCertificateInfo(cert, cal.ToLocalTime());
		    }
		    X509Certificate signCert = certs[0];
		    X509Certificate issuerCert = (certs.Length > 1 ? certs[1] : null);
		    Console.WriteLine("=== Checking validity of the document at the time of signing ===");
		    CheckRevocation(pkcs7, signCert, issuerCert, cal);
		    Console.WriteLine("=== Checking validity of the document today ===");
		    CheckRevocation(pkcs7, signCert, issuerCert, DateTime.Now);
		    return pkcs7;
	    }
    	
	    public static void CheckRevocation(PdfPKCS7 pkcs7, X509Certificate signCert, X509Certificate issuerCert, DateTime date) {
		    List ocsps = new List();
		    if (pkcs7.Ocsp != null)
			    ocsps.Add(pkcs7.Ocsp);
		    OcspVerifier ocspVerifier = new OcspVerifier(null, ocsps);
		    List verification =
			    ocspVerifier.Verify(signCert, issuerCert, date);
		    if (verification.Count == 0) {
			    List crls = new List();
			    if (pkcs7.CRLs != null)
				    foreach (X509Crl crl in pkcs7.CRLs)
					    crls.Add(crl);
			    CrlVerifier crlVerifier = new CrlVerifier(null, crls);
			    verification.AddRange(crlVerifier.Verify(signCert, issuerCert, date));
		    }
		    if (verification.Count == 0)
			    Console.WriteLine("The signing certificate couldn't be verified");
		    else
			    foreach (VerificationOK v in verification)
				    Console.WriteLine(v);
	    }

	    public void ShowCertificateInfo(X509Certificate cert, DateTime signDate) {
		    Console.WriteLine("Issuer: " + cert.IssuerDN);
		    Console.WriteLine("Subject: " + cert.SubjectDN);
            Console.WriteLine("Valid from: " + cert.NotBefore.ToString("yyyy-MM-dd HH:mm:ss.ff"));
            Console.WriteLine("Valid to: " + cert.NotAfter.ToString("yyyy-MM-dd HH:mm:ss.ff"));
		    try {
			    cert.CheckValidity(signDate);
			    Console.WriteLine("The certificate was valid at the time of signing.");
		    } catch (CertificateExpiredException e) {
			    Console.WriteLine("The certificate was expired at the time of signing.");
		    } catch (CertificateNotYetValidException e) {
			    Console.WriteLine("The certificate wasn't valid yet at the time of signing.");
		    }
		    try {
			    cert.CheckValidity();
			    Console.WriteLine("The certificate is still valid.");
		    } catch (CertificateExpiredException e) {
			    Console.WriteLine("The certificate has expired.");
		    } catch (CertificateNotYetValidException e) {
			    Console.WriteLine("The certificate isn't valid yet.");
		    }
	    }

	    static void Main(String[] args) {
		    LoggerFactory.GetInstance().SetLogger(new SysoLogger());
		    C5_03_CertificateValidation app = new C5_03_CertificateValidation();
            
		    X509CertificateParser parser = new X509CertificateParser();
            app.certificates.Add(parser.ReadCertificate(new FileStream(ADOBE, FileMode.Open)));
            app.certificates.Add(parser.ReadCertificate(new FileStream(CACERT, FileMode.Open)));
            app.certificates.Add(parser.ReadCertificate(new FileStream(BRUNO, FileMode.Open)));
		    app.VerifySignatures(EXAMPLE1);
		    app.VerifySignatures(EXAMPLE2);
		    app.VerifySignatures(EXAMPLE3);
		    app.VerifySignatures(EXAMPLE4);
	    }
    }
}
C5_04_LTV.cs
/*
 * This class is part of the white paper entitled
 * "Digital Signatures for PDF documents"
 * written by Bruno Lowagie
 * 
 * For more info, go to: http://itextpdf.com/learn
 */

using System;
using System.Collections.Generic;
using System.IO;
using System.util;
using iTextSharp.text.log;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.security;

namespace signatures.chapter5 {
    class C5_04_LTV {
        public const String EXAMPLE1 = "../../../../results/chapter3/hello_token.pdf";
        public const String EXAMPLE2 = "../../../../results/chapter4/hello_smartcard_Signature.pdf";
        public const String EXAMPLE3 = "../../../../results/chapter3/hello_cacert_ocsp_ts.pdf";
        public const String DEST = "../../../../results/chapter5/ltv_{0}.pdf";
    	
	    public static void Main(String[] args) {
            LoggerFactory.GetInstance().SetLogger(new SysoLogger());
		    Properties properties = new Properties();
		    properties.Load(new FileStream("c:/home/blowagie/key.properties", FileMode.Open));
            String tsaUrl = properties["TSAURL"];
            String tsaUser = properties["TSAUSERNAME"];
            String tsaPass = properties["TSAPASSWORD"];
            C5_04_LTV app = new C5_04_LTV();
            ITSAClient tsa = new TSAClientBouncyCastle(tsaUrl, tsaUser, tsaPass, 6500, "SHA512");
            IOcspClient ocsp = new OcspClientBouncyCastle();
            app.AddLtv(EXAMPLE1, String.Format(DEST, 1), ocsp, new CrlClientOnline(), tsa);
            Console.WriteLine();
            app.AddLtv(EXAMPLE2, String.Format(DEST, 2), ocsp, new CrlClientOnline(), tsa);
            Console.WriteLine();
            app.AddLtv(EXAMPLE3, String.Format(DEST, 3), ocsp, new CrlClientOnline(), tsa);
            Console.WriteLine();
            app.AddLtv(String.Format(DEST, 1), String.Format(DEST, 4), null, new CrlClientOnline(), tsa);
	    }
    	
	    public void AddLtv(String src, String dest, IOcspClient ocsp, ICrlClient crl, ITSAClient tsa) {
            PdfReader r = new PdfReader(src);
            FileStream fos = new FileStream(dest, FileMode.Create);
            PdfStamper stp = PdfStamper.CreateSignature(r, fos, '\0', null, true);
            LtvVerification v = stp.LtvVerification;
            AcroFields fields = stp.AcroFields;
		    List names = fields.GetSignatureNames();
            String sigName = names[names.Count - 1];
		    PdfPKCS7 pkcs7 = fields.VerifySignature(sigName);
            if (pkcs7.IsTsp) 
        	    v.AddVerification(sigName, ocsp, crl, LtvVerification.CertificateOption.SIGNING_CERTIFICATE, LtvVerification.Level.OCSP_CRL, LtvVerification.CertificateInclusion.NO);
            else foreach (String name in names)
        		v.AddVerification(name, ocsp, crl, LtvVerification.CertificateOption.WHOLE_CHAIN, LtvVerification.Level.OCSP_CRL, LtvVerification.CertificateInclusion.NO);
            PdfSignatureAppearance sap = stp.SignatureAppearance;
            LtvTimestamp.Timestamp(sap, tsa, null); 
	    }
    }
}
C5_05_CheckLTV.cs
/*
 * This class is part of the white paper entitled
 * "Digital Signatures for PDF documents"
 * written by Bruno Lowagie
 * 
 * For more info, go to: http://itextpdf.com/learn
 */

using System;
using System.Collections.Generic;
using Org.BouncyCastle.X509;
using iTextSharp.text.log;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.security;

namespace signatures.chapter5 {
    class C5_05_CheckLTV {
        public const String EXAMPLE1 = "../../../../results/chapter5/ltv_1.pdf";
        public const String EXAMPLE2 = "../../../../results/chapter5/ltv_2.pdf";
        public const String EXAMPLE3 = "../../../../results/chapter5/ltv_3.pdf";
        public const String EXAMPLE4 = "../../../../results/chapter5/ltv_4.pdf";

	    public PdfPKCS7 VerifySignature(AcroFields fields, String name) {
		    Console.WriteLine("Signature covers whole document: " + fields.SignatureCoversWholeDocument(name));
		    Console.WriteLine("Document revision: " + fields.GetRevision(name) + " of " + fields.TotalRevisions);
            PdfPKCS7 pkcs7 = fields.VerifySignature(name);
            Console.WriteLine("Integrity check OK? " + pkcs7.Verify());
		    Console.WriteLine("Digest algorithm: " + pkcs7.GetHashAlgorithm());
		    Console.WriteLine("Encryption algorithm: " + pkcs7.GetEncryptionAlgorithm());
		    Console.WriteLine("Filter subtype: " + pkcs7.GetFilterSubtype());
		    X509Certificate cert = pkcs7.SigningCertificate;
		    Console.WriteLine("Name of the signer: " + CertificateInfo.GetSubjectFields(cert).GetField("CN"));
            return pkcs7;
	    }
    	
	    public void VerifySignatures(String path) {
		    Console.WriteLine(path);
            PdfReader reader = new PdfReader(path);
            AcroFields fields = reader.AcroFields;
            List names = fields.GetSignatureNames();
		    foreach (String name in names) {
			    Console.WriteLine("===== " + name + " =====");
			    VerifySignature(fields, name);
		    }
		    Console.WriteLine();
	    }
    	
	    public static void Main(String[] args) {
		    LoggerFactory.GetInstance().SetLogger(new SysoLogger());
		    C5_05_CheckLTV app = new C5_05_CheckLTV();
		    app.VerifySignatures(EXAMPLE1);
		    app.VerifySignatures(EXAMPLE2);
		    app.VerifySignatures(EXAMPLE3);
		    app.VerifySignatures(EXAMPLE4);
	    }
    }
}
C5_06_ValidateLTV.cs
/*
 * This class is part of the white paper entitled
 * "Digital Signatures for PDF documents"
 * written by Bruno Lowagie
 * 
 * For more info, go to: http://itextpdf.com/learn
 */

using System;
using System.Collections.Generic;
using System.IO;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.X509;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.security;

namespace signatures.chapter5 {
    class C5_06_ValidateLTV {
        public const String ADOBE = "../../../../resources/adobeRootCA.cer";
        public const String EXAMPLE1 = "../../../../results/chapter5/ltv_1.pdf";
        public const String EXAMPLE2 = "../../../../results/chapter5/ltv_2.pdf";
        public const String EXAMPLE3 = "../../../../results/chapter5/ltv_3.pdf";
        public const String EXAMPLE4 = "../../../../results/chapter5/ltv_4.pdf";
    	
	    static void Main(String[] args) {
		    C5_06_ValidateLTV app = new C5_06_ValidateLTV();
		    Console.WriteLine(EXAMPLE1);
		    app.Validate(new PdfReader(EXAMPLE1));
		    Console.WriteLine();
		    Console.WriteLine(EXAMPLE2);
		    app.Validate(new PdfReader(EXAMPLE2));
		    Console.WriteLine();
		    Console.WriteLine(EXAMPLE3);
		    app.Validate(new PdfReader(EXAMPLE3));
		    Console.WriteLine();
		    Console.WriteLine(EXAMPLE4);
		    app.Validate(new PdfReader(EXAMPLE4));
	    }

        class MyVerifier : CertificateVerifier {
            public MyVerifier(CertificateVerifier verifier) : base(verifier) {}

            override public List Verify(X509Certificate signCert, X509Certificate issuerCert, DateTime signDate) {
				Console.WriteLine(signCert.SubjectDN + ": ALL VERIFICATIONS DONE");
				return new List();
			}
        }
    	
	    public void Validate(PdfReader reader) {
		    List certificates = new List();
            X509CertificateParser parser = new X509CertificateParser();
	        FileStream file = new FileStream(ADOBE, FileMode.Open);
            certificates.Add(parser.ReadCertificate(file));
    		
		    MyVerifier custom = new MyVerifier(null);
    		
 		    LtvVerifier data = new LtvVerifier(reader);
	        data.Certificates = certificates;
 		    data.CertificateOption = LtvVerification.CertificateOption.WHOLE_CHAIN;
 		    data.Verifier = custom;
 		    data.OnlineCheckingAllowed = false;
 		    data.VerifyRootCertificate = false;
 		    List list = new List();
 		    try {
 			    data.Verify(list);
 		    }
 		    catch (GeneralSecurityException e) {
 			    Console.WriteLine(e.ToString());
 		    }
		    Console.WriteLine();
            if (list.Count == 0)
                Console.WriteLine("The document can't be verified");
 		    foreach (VerificationOK v in list)
 			    Console.WriteLine(v.ToString());
            file.Close();
	    }
    }
}
Contact

Still have questions? 

We're happy to answer your questions. Reach out to us and we'll get back to you shortly.

Contact us
Stay updated

Join 11,000+ subscribers and become an iText PDF expert by staying up to date with our new products, updates, tips, technical solutions and happenings.

Subscribe Now