Digital signatures - chapter 5
These examples were written in the context of the white paper Digital Signatures for PDF documents.
c5_01_signatureintegrity
JAVA
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<String> 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);
}
}
C#
C#
/*
* 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<String> 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
JAVA
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<FieldPosition> 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<String> 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);
}
}
C#
C#
/*
* 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<AcroFields.FieldPosition> 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<String> 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
JAVA
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<VerificationException> 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<BasicOCSPResp> ocsps = new ArrayList<BasicOCSPResp>();
if (pkcs7.getOcsp() != null)
ocsps.add(pkcs7.getOcsp());
OCSPVerifier ocspVerifier = new OCSPVerifier(null, ocsps);
List<VerificationOK> verification =
ocspVerifier.verify(signCert, issuerCert, date);
if (verification.size() == 0) {
List<X509CRL> crls = new ArrayList<X509CRL>();
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);
}
}
C#
C#
/*
* 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<X509Certificate> certificates = new List<X509Certificate>();
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<BasicOcspResp> ocsps = new List<BasicOcspResp>();
if (pkcs7.Ocsp != null)
ocsps.Add(pkcs7.Ocsp);
OcspVerifier ocspVerifier = new OcspVerifier(null, ocsps);
List<VerificationOK> verification =
ocspVerifier.Verify(signCert, issuerCert, date);
if (verification.Count == 0) {
List<X509Crl> crls = new List<X509Crl>();
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
JAVA
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<String> 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);
}
}
C#
C#
/*
* 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<String> 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
JAVA
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<String> 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);
}
}
C#
C#
/*
* 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<String> 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
JAVA
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<VerificationOK> verify(X509Certificate signCert,
X509Certificate issuerCert, Date signDate)
throws GeneralSecurityException, IOException {
System.out.println(signCert.getSubjectDN().getName() + ": ALL VERIFICATIONS DONE");
return new ArrayList<VerificationOK>();
}
};
LtvVerifier data = new LtvVerifier(reader);
data.setRootStore(ks);
data.setCertificateOption(CertificateOption.WHOLE_CHAIN);
data.setVerifier(custom);
data.setOnlineCheckingAllowed(false);
data.setVerifyRootCertificate(false);
List<VerificationOK> list = new ArrayList<VerificationOK>();
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());
}
}
C#
C#
/*
* 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<VerificationOK> Verify(X509Certificate signCert, X509Certificate issuerCert, DateTime signDate) {
Console.WriteLine(signCert.SubjectDN + ": ALL VERIFICATIONS DONE");
return new List<VerificationOK>();
}
}
public void Validate(PdfReader reader) {
List<X509Certificate> certificates = new List<X509Certificate>();
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<VerificationOK> list = new List<VerificationOK>();
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();
}
}
}