Digital signatures - chapter 2
These examples were written in the context of the white paper Digital Signatures for PDF documents.
c2_01_signhelloworld
JAVA
JAVA
/*
* 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
*/
package signatures.chapter2;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Security;
import java.security.cert.Certificate;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfSignatureAppearance;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.security.BouncyCastleDigest;
import com.itextpdf.text.pdf.security.DigestAlgorithms;
import com.itextpdf.text.pdf.security.ExternalDigest;
import com.itextpdf.text.pdf.security.ExternalSignature;
import com.itextpdf.text.pdf.security.MakeSignature;
import com.itextpdf.text.pdf.security.MakeSignature.CryptoStandard;
import com.itextpdf.text.pdf.security.PrivateKeySignature;
public class C2_01_SignHelloWorld {
public static final String KEYSTORE = "src/main/resources/ks";
public static final char[] PASSWORD = "password".toCharArray();
public static final String SRC = "src/main/resources/hello.pdf";
public static final String DEST = "results/chapter2/hello_signed%s.pdf";
public void sign(String src, String dest,
Certificate[] chain,
PrivateKey pk, String digestAlgorithm, String provider,
CryptoStandard subfilter,
String reason, String location)
throws GeneralSecurityException, IOException, DocumentException {
// Creating the reader and the stamper
PdfReader reader = new PdfReader(src);
FileOutputStream os = new FileOutputStream(dest);
PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0');
// Creating the appearance
PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
appearance.setReason(reason);
appearance.setLocation(location);
appearance.setVisibleSignature(new Rectangle(36, 748, 144, 780), 1, "sig");
// Creating the signature
ExternalDigest digest = new BouncyCastleDigest();
ExternalSignature signature = new PrivateKeySignature(pk, digestAlgorithm, provider);
MakeSignature.signDetached(appearance, digest, signature, chain, null, null, null, 0, subfilter);
}
public static void main(String[] args) throws GeneralSecurityException, IOException, DocumentException {
BouncyCastleProvider provider = new BouncyCastleProvider();
Security.addProvider(provider);
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(new FileInputStream(KEYSTORE), PASSWORD);
String alias = (String)ks.aliases().nextElement();
PrivateKey pk = (PrivateKey) ks.getKey(alias, PASSWORD);
Certificate[] chain = ks.getCertificateChain(alias);
C2_01_SignHelloWorld app = new C2_01_SignHelloWorld();
app.sign(SRC, String.format(DEST, 1), chain, pk, DigestAlgorithms.SHA256, provider.getName(), CryptoStandard.CMS, "Test 1", "Ghent");
app.sign(SRC, String.format(DEST, 2), chain, pk, DigestAlgorithms.SHA512, provider.getName(), CryptoStandard.CMS, "Test 2", "Ghent");
app.sign(SRC, String.format(DEST, 3), chain, pk, DigestAlgorithms.SHA256, provider.getName(), CryptoStandard.CADES, "Test 3", "Ghent");
app.sign(SRC, String.format(DEST, 4), chain, pk, DigestAlgorithms.RIPEMD160, provider.getName(), CryptoStandard.CADES, "Test 4", "Ghent");
}
}
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.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.X509;
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.security;
namespace signatures.chapter2 {
class C2_01_SignHelloWorld {
public const String KEYSTORE = "../../../../resources/pkcs12";
public static char[] PASSWORD = "password".ToCharArray();
public const String SRC = "../../../../resources/hello.pdf";
public const String DEST = "../../../../results/chapter2/hello_signed{0}.pdf";
public void Sign(String src, String dest, ICollection<X509Certificate> chain, ICipherParameters pk,
String digestAlgorithm, CryptoStandard subfilter, String reason, String location) {
// Creating the reader and the stamper
PdfReader reader = new PdfReader(src);
FileStream os = new FileStream(dest, FileMode.Create);
PdfStamper stamper = PdfStamper.CreateSignature(reader, os, '\0');
// Creating the appearance
PdfSignatureAppearance appearance = stamper.SignatureAppearance;
appearance.Reason = reason;
appearance.Location = location;
appearance.SetVisibleSignature(new Rectangle(36, 748, 144, 780), 1, "sig");
// Creating the signature
IExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm);
MakeSignature.SignDetached(appearance, pks, chain, null, null, null, 0, subfilter);
}
public static void Main(String[] args) {
Pkcs12Store store = new Pkcs12Store(new FileStream(KEYSTORE, FileMode.Open), PASSWORD);
String alias = "";
ICollection<X509Certificate> chain = new List<X509Certificate>();
// searching for private key
foreach (string al in store.Aliases)
if (store.IsKeyEntry(al) && store.GetKey(al).Key.IsPrivate) {
alias = al;
break;
}
AsymmetricKeyEntry pk = store.GetKey(alias);
foreach (X509CertificateEntry c in store.GetCertificateChain(alias))
chain.Add(c.Certificate);
RsaPrivateCrtKeyParameters parameters = pk.Key as RsaPrivateCrtKeyParameters;
C2_01_SignHelloWorld app = new C2_01_SignHelloWorld();
app.Sign(SRC, String.Format(DEST, 1), chain, parameters, DigestAlgorithms.SHA256,
CryptoStandard.CMS, "Test 1", "Ghent");
app.Sign(SRC, String.Format(DEST, 2), chain, parameters, DigestAlgorithms.SHA512,
CryptoStandard.CMS, "Test 2", "Ghent");
app.Sign(SRC, String.Format(DEST, 3), chain, parameters, DigestAlgorithms.SHA256,
CryptoStandard.CADES, "Test 3", "Ghent");
app.Sign(SRC, String.Format(DEST, 4), chain, parameters, DigestAlgorithms.RIPEMD160,
CryptoStandard.CADES, "Test 4", "Ghent");
}
}
}
c2_02_signhelloworldwithtempfile
JAVA
JAVA
/*
* 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
*/
package signatures.chapter2;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Security;
import java.security.cert.Certificate;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfSignatureAppearance;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.security.BouncyCastleDigest;
import com.itextpdf.text.pdf.security.DigestAlgorithms;
import com.itextpdf.text.pdf.security.ExternalDigest;
import com.itextpdf.text.pdf.security.ExternalSignature;
import com.itextpdf.text.pdf.security.MakeSignature;
import com.itextpdf.text.pdf.security.MakeSignature.CryptoStandard;
import com.itextpdf.text.pdf.security.PrivateKeySignature;
public class C2_02_SignHelloWorldWithTempFile {
public static final String KEYSTORE = "src/main/resources/ks";
public static final char[] PASSWORD = "password".toCharArray();
public static final String SRC = "src/main/resources/hello.pdf";
public static final String TEMP = "results/chapter2/";
public static final String DEST = "results/chapter2/hello_signed_with_temp.pdf";
public void sign(String src, String tmp, String dest,
Certificate[] chain, PrivateKey pk,
String digestAlgorithm, String provider,
CryptoStandard subfilter,
String reason, String location)
throws GeneralSecurityException, IOException, DocumentException {
// Creating the reader and the stamper
PdfReader reader = new PdfReader(src);
FileOutputStream os = new FileOutputStream(dest);
PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0', new File(tmp));
// Creating the appearance
PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
appearance.setReason(reason);
appearance.setLocation(location);
appearance.setVisibleSignature(new Rectangle(36, 748, 144, 780), 1, "sig");
// Creating the signature
ExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm, provider);
ExternalDigest digest = new BouncyCastleDigest();
MakeSignature.signDetached(appearance, digest, pks, chain, null, null, null, 0, subfilter);
}
public static void main(String[] args) throws GeneralSecurityException, IOException, DocumentException {
BouncyCastleProvider provider = new BouncyCastleProvider();
Security.addProvider(provider);
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(new FileInputStream(KEYSTORE), PASSWORD);
String alias = (String)ks.aliases().nextElement();
PrivateKey pk = (PrivateKey) ks.getKey(alias, PASSWORD);
Certificate[] chain = ks.getCertificateChain(alias);
C2_02_SignHelloWorldWithTempFile app = new C2_02_SignHelloWorldWithTempFile();
app.sign(SRC, TEMP, DEST, chain, pk, DigestAlgorithms.SHA256, provider.getName(), CryptoStandard.CMS, "Temp test", "Ghent");
}
}
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.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.X509;
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.security;
namespace signatures.chapter2 {
class C2_02_SignHelloWorldWithTempFile {
public const String KEYSTORE = "../../../../resources/pkcs12";
public static char[] PASSWORD = "password".ToCharArray();
public const String SRC = "../../../../resources/hello.pdf";
public const String TEMP = "../../../../results/chapter2/";
public const String DEST = "../../../../results/chapter2/hello_signed_with_temp.pdf";
public void Sign(String src, String tmp, String dest, ICollection<X509Certificate> chain,
ICipherParameters pk, String digestAlgorithm, CryptoStandard subfilter,String reason, String location) {
// Creating the reader and the stamper
PdfReader reader = new PdfReader(src);
FileStream os = new FileStream(dest, FileMode.Create);
PdfStamper stamper = PdfStamper.CreateSignature(reader, os, '\0', tmp);
// Creating the appearance
PdfSignatureAppearance appearance = stamper.SignatureAppearance;
appearance.Reason = reason;
appearance.Location = location;
appearance.SetVisibleSignature(new Rectangle(36, 748, 144, 780), 1, "sig");
// Creating the signature
IExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm);
MakeSignature.SignDetached(appearance, pks, chain, null, null, null, 0, subfilter);
}
static void Main(string[] args) {
Pkcs12Store store = new Pkcs12Store(new FileStream(KEYSTORE, FileMode.Open), PASSWORD);
String alias = "";
ICollection<X509Certificate> chain = new List<X509Certificate>();
// searching for private key
foreach (string al in store.Aliases)
if (store.IsKeyEntry(al) && store.GetKey(al).Key.IsPrivate) {
alias = al;
break;
}
AsymmetricKeyEntry pk = store.GetKey(alias);
foreach (X509CertificateEntry c in store.GetCertificateChain(alias))
chain.Add(c.Certificate);
RsaPrivateCrtKeyParameters parameters = pk.Key as RsaPrivateCrtKeyParameters;
C2_02_SignHelloWorldWithTempFile app = new C2_02_SignHelloWorldWithTempFile();
app.Sign(SRC, TEMP, DEST, chain, parameters, DigestAlgorithms.SHA256,
CryptoStandard.CMS, "Temp test", "Ghent");
}
}
}
c2_03_signemptyfield
JAVA
JAVA
/*
* 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
*/
package signatures.chapter2;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Security;
import java.security.cert.Certificate;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfSignatureAppearance;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.security.BouncyCastleDigest;
import com.itextpdf.text.pdf.security.DigestAlgorithms;
import com.itextpdf.text.pdf.security.ExternalDigest;
import com.itextpdf.text.pdf.security.ExternalSignature;
import com.itextpdf.text.pdf.security.MakeSignature;
import com.itextpdf.text.pdf.security.MakeSignature.CryptoStandard;
import com.itextpdf.text.pdf.security.PrivateKeySignature;
public class C2_03_SignEmptyField {
public static final String KEYSTORE = "src/main/resources/ks";
public static final char[] PASSWORD = "password".toCharArray();
public static final String SRC = "src/main/resources/hello_to_sign.pdf";
public static final String DEST = "results/chapter2/field_signed%s.pdf";
public void sign(String src, String name, String dest,
Certificate[] chain, PrivateKey pk,
String digestAlgorithm, String provider, CryptoStandard subfilter,
String reason, String location)
throws GeneralSecurityException, IOException, DocumentException {
// Creating the reader and the stamper
PdfReader reader = new PdfReader(src);
FileOutputStream os = new FileOutputStream(dest);
PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0');
// Creating the appearance
PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
appearance.setReason(reason);
appearance.setLocation(location);
appearance.setVisibleSignature(name);
// Creating the signature
ExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm, provider);
ExternalDigest digest = new BouncyCastleDigest();
MakeSignature.signDetached(appearance, digest, pks, chain, null, null, null, 0, subfilter);
}
public static void main(String[] args) throws GeneralSecurityException, IOException, DocumentException {
BouncyCastleProvider provider = new BouncyCastleProvider();
Security.addProvider(provider);
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(new FileInputStream(KEYSTORE), PASSWORD);
String alias = (String)ks.aliases().nextElement();
PrivateKey pk = (PrivateKey) ks.getKey(alias, PASSWORD);
Certificate[] chain = ks.getCertificateChain(alias);
C2_03_SignEmptyField app = new C2_03_SignEmptyField();
app.sign(SRC, "Signature1", String.format(DEST, 1), chain, pk, DigestAlgorithms.SHA256, provider.getName(), CryptoStandard.CMS, "Test 1", "Ghent");
app.sign(SRC, "Signature1", String.format(DEST, 2), chain, pk, DigestAlgorithms.SHA512, provider.getName(), CryptoStandard.CMS, "Test 2", "Ghent");
app.sign(SRC, "Signature1", String.format(DEST, 3), chain, pk, DigestAlgorithms.SHA256, provider.getName(), CryptoStandard.CADES, "Test 3", "Ghent");
app.sign(SRC, "Signature1", String.format(DEST, 4), chain, pk, DigestAlgorithms.RIPEMD160, provider.getName(), CryptoStandard.CADES, "Test 4", "Ghent");
}
}
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.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.X509;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.security;
namespace signatures.chapter2 {
public class C2_03_SignEmptyField {
public static String KEYSTORE = "../../../../resources/pkcs12";
public static char[] PASSWORD = "password".ToCharArray();
public static String SRC = "../../../../resources/hello_to_sign.pdf";
public static String DEST = "../../../../results/chapter2/field_signed{0}.pdf";
public void Sign(String src, String name, String dest,
ICollection<X509Certificate> chain, ICipherParameters pk,
String digestAlgorithm, CryptoStandard subfilter,
String reason, String location) {
// Creating the reader and the stamper
PdfReader reader = new PdfReader(src);
FileStream os = new FileStream(dest, FileMode.Create);
PdfStamper stamper = PdfStamper.CreateSignature(reader, os, '\0');
// Creating the appearance
PdfSignatureAppearance appearance = stamper.SignatureAppearance;
appearance.Reason = reason;
appearance.Location = location;
appearance.SetVisibleSignature(name);
// Creating the signature
IExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm);
//ExternalDigest digest = new BouncyCastleDigest();
MakeSignature.SignDetached(appearance, pks, chain, null, null, null, 0, subfilter);
}
public static void Main(String[] args) {
Pkcs12Store store = new Pkcs12Store(new FileStream(KEYSTORE, FileMode.Open), PASSWORD);
String alias = "";
ICollection<X509Certificate> chain = new List<X509Certificate>();
// searching for private key
foreach (string al in store.Aliases) {
if (store.IsKeyEntry(al) && store.GetKey(al).Key.IsPrivate) {
alias = al;
break;
}
}
AsymmetricKeyEntry pk = store.GetKey(alias);
foreach (X509CertificateEntry c in store.GetCertificateChain(alias)) {
chain.Add(c.Certificate);
}
RsaPrivateCrtKeyParameters parameters = pk.Key as RsaPrivateCrtKeyParameters;
C2_03_SignEmptyField app = new C2_03_SignEmptyField();
app.Sign(SRC, "Signature1", String.Format(DEST, 1), chain, parameters, DigestAlgorithms.SHA256,
CryptoStandard.CMS, "Test 1", "Ghent");
app.Sign(SRC, "Signature1", String.Format(DEST, 2), chain, parameters, DigestAlgorithms.SHA512,
CryptoStandard.CMS, "Test 2", "Ghent");
app.Sign(SRC, "Signature1", String.Format(DEST, 3), chain, parameters, DigestAlgorithms.SHA256,
CryptoStandard.CADES, "Test 3", "Ghent");
app.Sign(SRC, "Signature1", String.Format(DEST, 4), chain, parameters, DigestAlgorithms.RIPEMD160,
CryptoStandard.CADES, "Test 4", "Ghent");
}
}
}
c2_04_createemptyfield
JAVA
JAVA
/*
* 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
*/
package signatures.chapter2;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Security;
import java.security.cert.Certificate;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.PdfAnnotation;
import com.itextpdf.text.pdf.PdfAppearance;
import com.itextpdf.text.pdf.PdfFormField;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.pdf.security.DigestAlgorithms;
import com.itextpdf.text.pdf.security.MakeSignature.CryptoStandard;
public class C2_04_CreateEmptyField {
public static final String KEYSTORE = "src/main/resources/ks";
public static final char[] PASSWORD = "password".toCharArray();
public static final String UNSIGNED = "results/chapter2/hello_empty.pdf";
public static final String SIGNAME = "Signature1";
public static final String DEST = "results/chapter2/field_signed.pdf";
public static final String SRC = "src/main/resources/hello.pdf";
public static final String UNSIGNED2 = "results/chapter2/hello_empty2.pdf";
public void createPdf(String filename) throws IOException, DocumentException {
// step 1: Create a Document
Document document = new Document();
// step 2: Create a PdfWriter
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(filename));
// step 3: Open the Document
document.open();
// step 4: Add content
document.add(new Paragraph("Hello World!"));
// create a signature form field
PdfFormField field = PdfFormField.createSignature(writer);
field.setFieldName(SIGNAME);
// set the widget properties
field.setPage();
field.setWidget(new Rectangle(72, 732, 144, 780), PdfAnnotation.HIGHLIGHT_INVERT);
field.setFlags(PdfAnnotation.FLAGS_PRINT);
// add it as an annotation
writer.addAnnotation(field);
// maybe you want to define an appearance
PdfAppearance tp = PdfAppearance.createAppearance(writer, 72, 48);
tp.setColorStroke(BaseColor.BLUE);
tp.setColorFill(BaseColor.LIGHT_GRAY);
tp.rectangle(0.5f, 0.5f, 71.5f, 47.5f);
tp.fillStroke();
tp.setColorFill(BaseColor.BLUE);
ColumnText.showTextAligned(tp, Element.ALIGN_CENTER, new Phrase("SIGN HERE"), 36, 24, 25);
field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, tp);
// step 5: Close the Document
document.close();
}
public void addField(String src, String dest) throws IOException, DocumentException {
PdfReader reader = new PdfReader(src);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
// create a signature form field
PdfFormField field = PdfFormField.createSignature(stamper.getWriter());
field.setFieldName(SIGNAME);
// set the widget properties
field.setWidget(new Rectangle(72, 732, 144, 780), PdfAnnotation.HIGHLIGHT_OUTLINE);
field.setFlags(PdfAnnotation.FLAGS_PRINT);
// add the annotation
stamper.addAnnotation(field, 1);
// close the stamper
stamper.close();
}
public static void main(String[] args) throws IOException, DocumentException, GeneralSecurityException {
C2_04_CreateEmptyField appCreate = new C2_04_CreateEmptyField();
appCreate.createPdf(UNSIGNED);
appCreate.addField(SRC, UNSIGNED2);
BouncyCastleProvider provider = new BouncyCastleProvider();
Security.addProvider(provider);
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(new FileInputStream(KEYSTORE), PASSWORD);
String alias = (String)ks.aliases().nextElement();
PrivateKey pk = (PrivateKey) ks.getKey(alias, PASSWORD);
Certificate[] chain = ks.getCertificateChain(alias);
C2_03_SignEmptyField appSign = new C2_03_SignEmptyField();
appSign.sign(UNSIGNED, SIGNAME, DEST, chain, pk, DigestAlgorithms.SHA256, provider.getName(), CryptoStandard.CMS, "Test", "Ghent");
}
}
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.Crypto.Parameters;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.X509;
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.security;
namespace signatures.chapter2 {
class C2_04_CreateEmptyField {
public const String KEYSTORE = "../../../../resources/pkcs12";
public static char[] PASSWORD = "password".ToCharArray();
public const String SRC = "../../../../resources/hello.pdf";
public const String SIGNAME = "Signature1";
public const String DEST = "../../../../results/chapter2/field_signed.pdf";
public const String UNSIGNED = "../../../../results/chapter2/hello_empty.pdf";
public const String UNSIGNED2 = "../../../../results/chapter2/hello_empty.pdf2";
public void CreatePdf(String filename) {
// step 1: Create a Document
Document document = new Document();
// step 2: Create a PdfWriter
PdfWriter writer = PdfWriter.GetInstance(document, new FileStream(filename, FileMode.Create));
// step 3: Open the Document
document.Open();
// step 4: Add content
document.Add(new Paragraph("Hello World!"));
// create a signature form field
PdfFormField field = PdfFormField.CreateSignature(writer);
field.FieldName = SIGNAME;
// set the widget properties
field.SetPage();
field.SetWidget(new Rectangle(72, 732, 144, 780), PdfAnnotation.HIGHLIGHT_INVERT);
field.Flags = PdfAnnotation.FLAGS_PRINT;
// add it as an annotation
writer.AddAnnotation(field);
// maybe you want to define an appearance
PdfAppearance tp = PdfAppearance.CreateAppearance(writer, 72, 48);
tp.SetColorStroke(BaseColor.BLUE);
tp.SetColorFill(BaseColor.LIGHT_GRAY);
tp.Rectangle(0.5f, 0.5f, 71.5f, 47.5f);
tp.FillStroke();
tp.SetColorFill(BaseColor.BLUE);
ColumnText.ShowTextAligned(tp, Element.ALIGN_CENTER, new Phrase("SIGN HERE"), 36, 24, 25);
field.SetAppearance(PdfAnnotation.APPEARANCE_NORMAL, tp);
// step 5: Close the Document
document.Close();
}
public void AddField(String src, String dest) {
PdfReader reader = new PdfReader(src);
PdfStamper stamper = new PdfStamper(reader, new FileStream(dest, FileMode.Create));
// create a signature form field
PdfFormField field = PdfFormField.CreateSignature(stamper.Writer);
field.FieldName = SIGNAME;
// set the widget properties
field.SetWidget(new Rectangle(72, 732, 144, 780), PdfAnnotation.HIGHLIGHT_OUTLINE);
field.Flags = PdfAnnotation.FLAGS_PRINT;
// add the annotation
stamper.AddAnnotation(field, 1);
// close the stamper
stamper.Close();
}
static void Main(string[] args) {
C2_04_CreateEmptyField appCreate = new C2_04_CreateEmptyField();
appCreate.CreatePdf(UNSIGNED);
appCreate.AddField(SRC, UNSIGNED2);
Pkcs12Store store = new Pkcs12Store(new FileStream(KEYSTORE, FileMode.Open), PASSWORD);
String alias = "";
ICollection<X509Certificate> chain = new List<X509Certificate>();
// searching for private key
foreach (string al in store.Aliases)
if (store.IsKeyEntry(al) && store.GetKey(al).Key.IsPrivate)
{
alias = al;
break;
}
AsymmetricKeyEntry pk = store.GetKey(alias);
foreach (X509CertificateEntry c in store.GetCertificateChain(alias))
chain.Add(c.Certificate);
RsaPrivateCrtKeyParameters parameters = pk.Key as RsaPrivateCrtKeyParameters;
C2_03_SignEmptyField appSign = new C2_03_SignEmptyField();
appSign.Sign(UNSIGNED, SIGNAME, DEST, chain, parameters, DigestAlgorithms.SHA256, CryptoStandard.CMS, "Test", "Ghent");
}
}
}
c2_05_customappearance
JAVA
JAVA
/*
* 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
*/
package signatures.chapter2;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Security;
import java.security.cert.Certificate;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfSignatureAppearance;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.PdfTemplate;
import com.itextpdf.text.pdf.security.BouncyCastleDigest;
import com.itextpdf.text.pdf.security.DigestAlgorithms;
import com.itextpdf.text.pdf.security.ExternalDigest;
import com.itextpdf.text.pdf.security.ExternalSignature;
import com.itextpdf.text.pdf.security.MakeSignature;
import com.itextpdf.text.pdf.security.MakeSignature.CryptoStandard;
import com.itextpdf.text.pdf.security.PrivateKeySignature;
public class C2_05_CustomAppearance {
public static final String KEYSTORE = "src/main/resources/ks";
public static final char[] PASSWORD = "password".toCharArray();
public static final String SRC = "src/main/resources/hello_to_sign.pdf";
public static final String DEST = "results/chapter2/signature_custom.pdf";
public void sign(String src, String name, String dest,
Certificate[] chain, PrivateKey pk,
String digestAlgorithm, String provider,
CryptoStandard subfilter,
String reason, String location)
throws GeneralSecurityException, IOException, DocumentException {
// Creating the reader and the stamper
PdfReader reader = new PdfReader(src);
FileOutputStream os = new FileOutputStream(dest);
PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0');
// Creating the appearance
PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
appearance.setReason(reason);
appearance.setLocation(location);
appearance.setVisibleSignature(name);
// Creating the appearance for layer 0
PdfTemplate n0 = appearance.getLayer(0);
float x = n0.getBoundingBox().getLeft();
float y = n0.getBoundingBox().getBottom();
float width = n0.getBoundingBox().getWidth();
float height = n0.getBoundingBox().getHeight();
n0.setColorFill(BaseColor.LIGHT_GRAY);
n0.rectangle(x, y, width, height);
n0.fill();
// Creating the appearance for layer 2
PdfTemplate n2 = appearance.getLayer(2);
ColumnText ct = new ColumnText(n2);
ct.setSimpleColumn(n2.getBoundingBox());
Paragraph p = new Paragraph("This document was signed by Bruno Specimen.");
ct.addElement(p);
ct.go();
// Creating the signature
ExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm, provider);
ExternalDigest digest = new BouncyCastleDigest();
MakeSignature.signDetached(appearance, digest, pks, chain, null, null, null, 0, subfilter);
}
public static void main(String[] args) throws GeneralSecurityException, IOException, DocumentException {
BouncyCastleProvider provider = new BouncyCastleProvider();
Security.addProvider(provider);
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(new FileInputStream(KEYSTORE), PASSWORD);
String alias = (String)ks.aliases().nextElement();
PrivateKey pk = (PrivateKey) ks.getKey(alias, PASSWORD);
Certificate[] chain = ks.getCertificateChain(alias);
C2_05_CustomAppearance app = new C2_05_CustomAppearance();
app.sign(SRC, "Signature1", DEST, chain, pk,
DigestAlgorithms.SHA256, provider.getName(), CryptoStandard.CMS,
"Custom appearance example", "Ghent");
}
}
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.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.X509;
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.security;
namespace signatures.chapter2 {
class C2_05_CustomAppearance {
public const String KEYSTORE = "../../../../resources/pkcs12";
public static char[] PASSWORD = "password".ToCharArray();
public const String SRC = "../../../../resources/hello_to_sign.pdf";
public const String DEST = "../../../../results/chapter2/signature_custom.pdf";
public void Sign(String src, String name, String dest, ICollection<X509Certificate> chain, ICipherParameters pk,
String digestAlgorithm, CryptoStandard subfilter, String reason, String location) {
// Creating the reader and the stamper
PdfReader reader = new PdfReader(src);
FileStream os = new FileStream(dest, FileMode.Create);
PdfStamper stamper = PdfStamper.CreateSignature(reader, os, '\0');
// Creating the appearance
PdfSignatureAppearance appearance = stamper.SignatureAppearance;
appearance.Reason = reason;
appearance.Location = location;
appearance.SetVisibleSignature(name);
// Creating the appearance for layer 0
PdfTemplate n0 = appearance.GetLayer(0);
float x = n0.BoundingBox.Left;
float y = n0.BoundingBox.Bottom;
float width = n0.BoundingBox.Width;
float height = n0.BoundingBox.Height;
n0.SetColorFill(BaseColor.LIGHT_GRAY);
n0.Rectangle(x, y, width, height);
n0.Fill();
// Creating the appearance for layer 2
PdfTemplate n2 = appearance.GetLayer(2);
ColumnText ct = new ColumnText(n2);
ct.SetSimpleColumn(n2.BoundingBox);
Paragraph p = new Paragraph("This document was signed by Bruno Specimen.");
ct.AddElement(p);
ct.Go();
// Creating the signature
IExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm);
MakeSignature.SignDetached(appearance, pks, chain, null, null, null, 0, subfilter);
}
static void Main(string[] args) {
Pkcs12Store store = new Pkcs12Store(new FileStream(KEYSTORE, FileMode.Open), PASSWORD);
String alias = "";
ICollection<X509Certificate> chain = new List<X509Certificate>();
// searching for private key
foreach (string al in store.Aliases)
if (store.IsKeyEntry(al) && store.GetKey(al).Key.IsPrivate) {
alias = al;
break;
}
AsymmetricKeyEntry pk = store.GetKey(alias);
foreach (X509CertificateEntry c in store.GetCertificateChain(alias))
chain.Add(c.Certificate);
RsaPrivateCrtKeyParameters parameters = pk.Key as RsaPrivateCrtKeyParameters;
C2_05_CustomAppearance app = new C2_05_CustomAppearance();
app.Sign(SRC, "Signature1", DEST, chain, parameters, DigestAlgorithms.SHA256,
CryptoStandard.CMS, "Custom appearance example", "Ghent");
}
}
}
c2_06_signatureappearance
JAVA
JAVA
/*
* 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
*/
package signatures.chapter2;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Security;
import java.security.cert.Certificate;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Font;
import com.itextpdf.text.Image;
import com.itextpdf.text.Font.FontFamily;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfSignatureAppearance;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.security.BouncyCastleDigest;
import com.itextpdf.text.pdf.security.DigestAlgorithms;
import com.itextpdf.text.pdf.security.ExternalDigest;
import com.itextpdf.text.pdf.security.MakeSignature;
import com.itextpdf.text.pdf.security.MakeSignature.CryptoStandard;
import com.itextpdf.text.pdf.security.PrivateKeySignature;
public class C2_06_SignatureAppearance {
public static final String KEYSTORE = "src/main/resources/ks";
public static final char[] PASSWORD = "password".toCharArray();
public static final String IMG = "src/main/resources/1t3xt.gif";
public static final String SRC = "src/main/resources/hello_to_sign.pdf";
public static final String DEST = "results/chapter2/signature_appearance%s.pdf";
public void sign1(String src, String name, String dest,
Certificate[] chain, PrivateKey pk,
String digestAlgorithm, String provider, CryptoStandard subfilter,
String reason, String location)
throws GeneralSecurityException, IOException, DocumentException {
// Creating the reader and the stamper
PdfReader reader = new PdfReader(src);
FileOutputStream os = new FileOutputStream(dest);
PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0');
// Creating the appearance
PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
appearance.setReason(reason);
appearance.setLocation(location);
appearance.setVisibleSignature(name);
// Custom text and custom font
appearance.setLayer2Text("This document was signed by Bruno Specimen");
appearance.setLayer2Font(new Font(FontFamily.TIMES_ROMAN));
// Creating the signature
PrivateKeySignature pks = new PrivateKeySignature(pk, digestAlgorithm, provider);
ExternalDigest digest = new BouncyCastleDigest();
MakeSignature.signDetached(appearance, digest, pks, chain, null, null, null, 0, subfilter);
}
public void sign2(String src, String name, String dest,
Certificate[] chain, PrivateKey pk,
String digestAlgorithm, String provider, CryptoStandard subfilter,
String reason, String location)
throws GeneralSecurityException, IOException, DocumentException {
// Creating the reader and the stamper
PdfReader reader = new PdfReader(src);
FileOutputStream os = new FileOutputStream(dest);
PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0');
// Creating the appearance
PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
appearance.setReason(reason);
appearance.setLocation(location);
appearance.setVisibleSignature(name);
// Custom text, custom font, and right-to-left writing
appearance.setLayer2Text("\u0644\u0648\u0631\u0627\u0646\u0633 \u0627\u0644\u0639\u0631\u0628");
appearance.setRunDirection(PdfWriter.RUN_DIRECTION_RTL);
appearance.setLayer2Font(new Font(BaseFont.createFont("C:/windows/fonts/arialuni.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED), 12));
// Creating the signature
PrivateKeySignature pks = new PrivateKeySignature(pk, digestAlgorithm, provider);
ExternalDigest digest = new BouncyCastleDigest();
MakeSignature.signDetached(appearance, digest, pks, chain, null, null, null, 0, subfilter);
}
public void sign3(String src, String name, String dest,
Certificate[] chain, PrivateKey pk,
String digestAlgorithm, String provider, CryptoStandard subfilter,
String reason, String location)
throws GeneralSecurityException, IOException, DocumentException {
// Creating the reader and the stamper
PdfReader reader = new PdfReader(src);
FileOutputStream os = new FileOutputStream(dest);
PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0');
// Creating the appearance
PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
appearance.setReason(reason);
appearance.setLocation(location);
appearance.setVisibleSignature(name);
// Custom text and background image
appearance.setLayer2Text("This document was signed by Bruno Specimen");
appearance.setImage(Image.getInstance(IMG));
appearance.setImageScale(1);
// Creating the signature
PrivateKeySignature pks = new PrivateKeySignature(pk, digestAlgorithm, provider);
ExternalDigest digest = new BouncyCastleDigest();
MakeSignature.signDetached(appearance, digest, pks, chain, null, null, null, 0, subfilter);
}
public void sign4(String src, String name, String dest,
Certificate[] chain, PrivateKey pk,
String digestAlgorithm, String provider, CryptoStandard subfilter,
String reason, String location)
throws GeneralSecurityException, IOException, DocumentException {
// Creating the reader and the stamper
PdfReader reader = new PdfReader(src);
FileOutputStream os = new FileOutputStream(dest);
PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0');
// Creating the appearance
PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
appearance.setReason(reason);
appearance.setLocation(location);
appearance.setVisibleSignature(name);
// Default text and scaled background image
appearance.setImage(Image.getInstance(IMG));
appearance.setImageScale(-1);
// Creating the signature
PrivateKeySignature pks = new PrivateKeySignature(pk, digestAlgorithm, provider);
ExternalDigest digest = new BouncyCastleDigest();
MakeSignature.signDetached(appearance, digest, pks, chain, null, null, null, 0, subfilter);
}
public static void main(String[] args) throws GeneralSecurityException, IOException, DocumentException {
BouncyCastleProvider provider = new BouncyCastleProvider();
Security.addProvider(provider);
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(new FileInputStream(KEYSTORE), PASSWORD);
String alias = (String)ks.aliases().nextElement();
PrivateKey pk = (PrivateKey) ks.getKey(alias, PASSWORD);
Certificate[] chain = ks.getCertificateChain(alias);
C2_06_SignatureAppearance app = new C2_06_SignatureAppearance();
app.sign1(SRC, "Signature1", String.format(DEST, 1), chain, pk,
DigestAlgorithms.SHA256, provider.getName(), CryptoStandard.CMS,
"Custom appearance example", "Ghent");
app.sign2(SRC, "Signature1", String.format(DEST, 2), chain, pk,
DigestAlgorithms.SHA256, provider.getName(), CryptoStandard.CMS,
"Custom appearance example", "Ghent");
app.sign3(SRC, "Signature1", String.format(DEST, 3), chain, pk,
DigestAlgorithms.SHA256, provider.getName(), CryptoStandard.CMS,
"Custom appearance example", "Ghent");
app.sign4(SRC, "Signature1", String.format(DEST, 4), chain, pk,
DigestAlgorithms.SHA256, provider.getName(), CryptoStandard.CMS,
"Custom appearance example", "Ghent");
}
}
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.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.X509;
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.security;
namespace signatures.chapter2 {
class C2_06_SignatureAppearance {
public const String KEYSTORE = "../../../../resources/pkcs12";
public static char[] PASSWORD = "password".ToCharArray();
public const String SRC = "../../../../resources/hello_to_sign.pdf";
public const String DEST = "../../../../results/chapter2/signature_appearance{0}.pdf";
public const String IMG = "../../../../resources/1t3xt.gif";
public void Sign1(String src, String name, String dest, ICollection<X509Certificate> chain, ICipherParameters pk,
String digestAlgorithm, CryptoStandard subfilter, String reason, String location) {
// Creating the reader and the stamper
PdfReader reader = new PdfReader(src);
FileStream os = new FileStream(dest, FileMode.Create);
PdfStamper stamper = PdfStamper.CreateSignature(reader, os, '\0');
// Creating the appearance
PdfSignatureAppearance appearance = stamper.SignatureAppearance;
appearance.Reason = reason;
appearance.Location = location;
appearance.SetVisibleSignature(name);
// Custom text and custom font
appearance.Layer2Text = "This document was signed by Bruno Specimen";
appearance.Layer2Font = new Font(Font.FontFamily.TIMES_ROMAN);
// Creating the signature
IExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm);
MakeSignature.SignDetached(appearance, pks, chain, null, null, null, 0, subfilter);
}
public void Sign2(String src, String name, String dest, ICollection<X509Certificate> chain, ICipherParameters pk,
String digestAlgorithm, CryptoStandard subfilter, String reason, String location) {
// Creating the reader and the stamper
PdfReader reader = new PdfReader(src);
FileStream os = new FileStream(dest, FileMode.Create);
PdfStamper stamper = PdfStamper.CreateSignature(reader, os, '\0');
// Creating the appearance
PdfSignatureAppearance appearance = stamper.SignatureAppearance;
appearance.Reason = reason;
appearance.Location = location;
appearance.SetVisibleSignature(name);
// Custom text, custom font, and right-to-left writing
appearance.Layer2Text = "\u0644\u0648\u0631\u0627\u0646\u0633 \u0627\u0644\u0639\u0631\u0628";
appearance.RunDirection = PdfWriter.RUN_DIRECTION_RTL;
appearance.Layer2Font = new Font(BaseFont.CreateFont("C:/windows/fonts/arialuni.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED), 12);
// Creating the signature
IExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm);
MakeSignature.SignDetached(appearance, pks, chain, null, null, null, 0, subfilter);
}
public void Sign3(String src, String name, String dest, ICollection<X509Certificate> chain, ICipherParameters pk,
String digestAlgorithm, CryptoStandard subfilter, String reason, String location) {
// Creating the reader and the stamper
PdfReader reader = new PdfReader(src);
FileStream os = new FileStream(dest, FileMode.Create);
PdfStamper stamper = PdfStamper.CreateSignature(reader, os, '\0');
// Creating the appearance
PdfSignatureAppearance appearance = stamper.SignatureAppearance;
appearance.Reason = reason;
appearance.Location = location;
appearance.SetVisibleSignature(name);
// Custom text and background image
appearance.Layer2Text = "This document was signed by Bruno Specimen";
appearance.Image = Image.GetInstance(IMG);
appearance.ImageScale = 1;
// Creating the signature
IExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm);
MakeSignature.SignDetached(appearance, pks, chain, null, null, null, 0, subfilter);
}
public void Sign4(String src, String name, String dest, ICollection<X509Certificate> chain, ICipherParameters pk,
String digestAlgorithm, CryptoStandard subfilter, String reason, String location) {
// Creating the reader and the stamper
PdfReader reader = new PdfReader(src);
FileStream os = new FileStream(dest, FileMode.Create);
PdfStamper stamper = PdfStamper.CreateSignature(reader, os, '\0');
// Creating the appearance
PdfSignatureAppearance appearance = stamper.SignatureAppearance;
appearance.Reason = reason;
appearance.Location = location;
appearance.SetVisibleSignature(name);
// Default text and scaled background image
appearance.Image = Image.GetInstance(IMG);
appearance.ImageScale = -1;
// Creating the signature
IExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm);
MakeSignature.SignDetached(appearance, pks, chain, null, null, null, 0, subfilter);
}
static void Main(string[] args) {
Pkcs12Store store = new Pkcs12Store(new FileStream(KEYSTORE, FileMode.Open), PASSWORD);
String alias = "";
ICollection<X509Certificate> chain = new List<X509Certificate>();
// searching for private key
foreach (string al in store.Aliases)
if (store.IsKeyEntry(al) && store.GetKey(al).Key.IsPrivate)
{
alias = al;
break;
}
AsymmetricKeyEntry pk = store.GetKey(alias);
foreach (X509CertificateEntry c in store.GetCertificateChain(alias))
chain.Add(c.Certificate);
RsaPrivateCrtKeyParameters parameters = pk.Key as RsaPrivateCrtKeyParameters;
C2_06_SignatureAppearance app = new C2_06_SignatureAppearance();
app.Sign1(SRC, "Signature1", String.Format(DEST, 1), chain, parameters, DigestAlgorithms.SHA256,
CryptoStandard.CMS, "Custom appearance example", "Ghent");
app.Sign2(SRC, "Signature1", String.Format(DEST, 2), chain, parameters, DigestAlgorithms.SHA256,
CryptoStandard.CMS, "Custom appearance example", "Ghent");
app.Sign3(SRC, "Signature1", String.Format(DEST, 3), chain, parameters, DigestAlgorithms.SHA256,
CryptoStandard.CMS, "Custom appearance example", "Ghent");
app.Sign4(SRC, "Signature1", String.Format(DEST, 4), chain, parameters, DigestAlgorithms.SHA256,
CryptoStandard.CMS, "Custom appearance example", "Ghent");
}
}
}
c2_07_signatureappearances
JAVA
JAVA
/*
* 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
*/
package signatures.chapter2;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Security;
import java.security.cert.Certificate;
import java.util.Date;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfSignatureAppearance;
import com.itextpdf.text.pdf.PdfSignatureAppearance.RenderingMode;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.security.BouncyCastleDigest;
import com.itextpdf.text.pdf.security.DigestAlgorithms;
import com.itextpdf.text.pdf.security.ExternalDigest;
import com.itextpdf.text.pdf.security.MakeSignature;
import com.itextpdf.text.pdf.security.MakeSignature.CryptoStandard;
import com.itextpdf.text.pdf.security.PrivateKeySignature;
public class C2_07_SignatureAppearances {
public static final String KEYSTORE = "src/main/resources/ks";
public static final char[] PASSWORD = "password".toCharArray();
public static final String IMG = "src/main/resources/1t3xt.gif";
public static final String SRC = "src/main/resources/hello_to_sign.pdf";
public static final String DEST = "results/chapter2/signature_appearance_%s.pdf";
public void sign(String src, String name, String dest,
Certificate[] chain, PrivateKey pk,
String digestAlgorithm, String provider,
CryptoStandard subfilter,
String reason, String location, RenderingMode renderingMode,
Image image)
throws GeneralSecurityException, IOException, DocumentException {
// Creating the reader and the stamper
PdfReader reader = new PdfReader(src);
FileOutputStream os = new FileOutputStream(dest);
PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0');
// Creating the appearance
PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
appearance.setReason(reason);
appearance.setLocation(location);
appearance.setVisibleSignature(name);
appearance.setLayer2Text("Signed on " + new Date().toString());
appearance.setRenderingMode(renderingMode);
appearance.setSignatureGraphic(image);
// Creating the signature
PrivateKeySignature pks = new PrivateKeySignature(pk, digestAlgorithm, provider);
ExternalDigest digest = new BouncyCastleDigest();
MakeSignature.signDetached(appearance, digest, pks, chain, null, null, null, 0, subfilter);
}
public static void main(String[] args) throws GeneralSecurityException, IOException, DocumentException {
BouncyCastleProvider provider = new BouncyCastleProvider();
Security.addProvider(provider);
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(new FileInputStream(KEYSTORE), PASSWORD);
String alias = (String)ks.aliases().nextElement();
PrivateKey pk = (PrivateKey) ks.getKey(alias, PASSWORD);
Certificate[] chain = ks.getCertificateChain(alias);
Image image = Image.getInstance(IMG);
C2_07_SignatureAppearances app = new C2_07_SignatureAppearances();
app.sign(SRC, "Signature1", String.format(DEST, 1), chain, pk,
DigestAlgorithms.SHA256, provider.getName(), CryptoStandard.CMS,
"Appearance 1", "Ghent", RenderingMode.DESCRIPTION, null);
app.sign(SRC, "Signature1", String.format(DEST, 2), chain, pk,
DigestAlgorithms.SHA256, provider.getName(), CryptoStandard.CMS,
"Appearance 2", "Ghent", RenderingMode.NAME_AND_DESCRIPTION, null);
app.sign(SRC, "Signature1", String.format(DEST, 3), chain, pk,
DigestAlgorithms.SHA256, provider.getName(), CryptoStandard.CMS,
"Appearance 3", "Ghent", RenderingMode.GRAPHIC_AND_DESCRIPTION, image);
app.sign(SRC, "Signature1", String.format(DEST, 4), chain, pk,
DigestAlgorithms.SHA256, provider.getName(), CryptoStandard.CMS,
"Appearance 4", "Ghent", RenderingMode.GRAPHIC, image);
}
}
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.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.X509;
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.security;
namespace signatures.chapter2 {
class C2_07_SignatureAppearances {
public const String KEYSTORE = "../../../../resources/pkcs12";
public static char[] PASSWORD = "password".ToCharArray();
public const String SRC = "../../../../resources/hello_to_sign.pdf";
public const String DEST = "../../../../results/chapter2/signature_appearance{0}.pdf";
public const String IMG = "../../../../resources/1t3xt.gif";
public void Sign(String src, String name, String dest, ICollection<X509Certificate> chain, ICipherParameters pk,
String digestAlgorithm, CryptoStandard subfilter, String reason, String location,
PdfSignatureAppearance.RenderingMode renderingMode, Image image) {
// Creating the reader and the stamper
PdfReader reader = new PdfReader(src);
FileStream os = new FileStream(dest, FileMode.Create);
PdfStamper stamper = PdfStamper.CreateSignature(reader, os, '\0');
// Creating the appearance
PdfSignatureAppearance appearance = stamper.SignatureAppearance;
appearance.Reason = reason;
appearance.Location = location;
appearance.SetVisibleSignature(name);
appearance.Layer2Text = "Signed on " + DateTime.Now;
appearance.SignatureRenderingMode = renderingMode;
appearance.SignatureGraphic = image;
// Creating the signature
IExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm);
MakeSignature.SignDetached(appearance, pks, chain, null, null, null, 0, subfilter);
}
static void Main(string[] args) {
Pkcs12Store store = new Pkcs12Store(new FileStream(KEYSTORE, FileMode.Open), PASSWORD);
String alias = "";
ICollection<X509Certificate> chain = new List<X509Certificate>();
// searching for private key
foreach (string al in store.Aliases)
if (store.IsKeyEntry(al) && store.GetKey(al).Key.IsPrivate) {
alias = al;
break;
}
AsymmetricKeyEntry pk = store.GetKey(alias);
foreach (X509CertificateEntry c in store.GetCertificateChain(alias))
chain.Add(c.Certificate);
Image image = Image.GetInstance(IMG);
RsaPrivateCrtKeyParameters parameters = pk.Key as RsaPrivateCrtKeyParameters;
C2_07_SignatureAppearances app = new C2_07_SignatureAppearances();
app.Sign(SRC, "Signature1", String.Format(DEST, 1), chain, parameters, DigestAlgorithms.SHA256,
CryptoStandard.CMS, "Appearance 1", "Ghent", PdfSignatureAppearance.RenderingMode.DESCRIPTION, null);
app.Sign(SRC, "Signature1", String.Format(DEST, 2), chain, parameters, DigestAlgorithms.SHA256,
CryptoStandard.CMS, "Appearance 2", "Ghent", PdfSignatureAppearance.RenderingMode.NAME_AND_DESCRIPTION, null);
app.Sign(SRC, "Signature1", String.Format(DEST, 3), chain, parameters, DigestAlgorithms.SHA256,
CryptoStandard.CMS, "Appearance 3", "Ghent", PdfSignatureAppearance.RenderingMode.GRAPHIC_AND_DESCRIPTION, image);
app.Sign(SRC, "Signature1", String.Format(DEST, 4), chain, parameters, DigestAlgorithms.SHA256,
CryptoStandard.CMS, "Appearance 4", "Ghent", PdfSignatureAppearance.RenderingMode.GRAPHIC, image);
}
}
}
c2_08_signaturemetadata
JAVA
JAVA
/*
* 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
*/
package signatures.chapter2;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Security;
import java.security.cert.Certificate;
import java.util.Calendar;
import java.util.GregorianCalendar;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfDictionary;
import com.itextpdf.text.pdf.PdfName;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfSignatureAppearance;
import com.itextpdf.text.pdf.PdfSignatureAppearance.SignatureEvent;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.PdfString;
import com.itextpdf.text.pdf.security.BouncyCastleDigest;
import com.itextpdf.text.pdf.security.DigestAlgorithms;
import com.itextpdf.text.pdf.security.ExternalDigest;
import com.itextpdf.text.pdf.security.MakeSignature;
import com.itextpdf.text.pdf.security.MakeSignature.CryptoStandard;
import com.itextpdf.text.pdf.security.PrivateKeySignature;
public class C2_08_SignatureMetadata {
public static final String KEYSTORE = "src/main/resources/ks";
public static final char[] PASSWORD = "password".toCharArray();
public static final String SRC = "src/main/resources/hello_to_sign.pdf";
public static final String DEST = "results/chapter2/field_metadata.pdf";
public void sign(String src, String name, String dest,
Certificate[] chain, PrivateKey pk,
String digestAlgorithm, String provider,
CryptoStandard subfilter,
String reason, String location, String contact, Calendar signDate,
final String fullName)
throws GeneralSecurityException, IOException, DocumentException {
// Creating the reader and the stamper
PdfReader reader = new PdfReader(src);
FileOutputStream os = new FileOutputStream(dest);
PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0');
// Creating the appearance
PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
appearance.setReason(reason);
appearance.setLocation(location);
appearance.setVisibleSignature(name);
appearance.setContact(contact);
appearance.setSignDate(signDate);
appearance.setSignatureEvent(
new SignatureEvent(){
public void getSignatureDictionary(PdfDictionary sig) {
sig.put(PdfName.NAME, new PdfString(fullName));
}
}
);
// Creating the signature
PrivateKeySignature pks = new PrivateKeySignature(pk, digestAlgorithm, provider);
ExternalDigest digest = new BouncyCastleDigest();
MakeSignature.signDetached(appearance, digest, pks, chain, null, null, null, 0, subfilter);
}
public static void main(String[] args) throws GeneralSecurityException, IOException, DocumentException {
BouncyCastleProvider provider = new BouncyCastleProvider();
Security.addProvider(provider);
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(new FileInputStream(KEYSTORE), PASSWORD);
String alias = (String)ks.aliases().nextElement();
PrivateKey pk = (PrivateKey) ks.getKey(alias, PASSWORD);
Certificate[] chain = ks.getCertificateChain(alias);
C2_08_SignatureMetadata app = new C2_08_SignatureMetadata();
app.sign(SRC, "Signature1", String.format(DEST, 1), chain, pk, DigestAlgorithms.SHA256, provider.getName(), CryptoStandard.CMS, "Test metadata", "Ghent", "555 123 456", new GregorianCalendar(2012, GregorianCalendar.AUGUST, 5), "Bruno L. Specimen");
}
}
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.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.X509;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.security;
namespace signatures.chapter2 {
class C2_08_SignatureMetadata {
public const String KEYSTORE = "../../../../resources/pkcs12";
public static char[] PASSWORD = "password".ToCharArray();
public const String SRC = "../../../../resources/hello_to_sign.pdf";
public const String DEST = "../../../../results/chapter2/field_metadata.pdf";
class MySignatureEvent : PdfSignatureAppearance.ISignatureEvent {
private String fullName;
public String FullName {
set { fullName = value; }
}
public void GetSignatureDictionary(PdfDictionary sig) {
sig.Put(PdfName.NAME, new PdfString(fullName));
}
}
public void Sign(String src, String name, String dest, ICollection<X509Certificate> chain, ICipherParameters pk,
String digestAlgorithm, CryptoStandard subfilter, String reason, String location,
String contact, DateTime signDate, String fullName) {
// Creating the reader and the stamper
PdfReader reader = new PdfReader(src);
FileStream os = new FileStream(dest, FileMode.Create);
PdfStamper stamper = PdfStamper.CreateSignature(reader, os, '\0');
// Creating the appearance
PdfSignatureAppearance appearance = stamper.SignatureAppearance;
appearance.Reason = reason;
appearance.Location = location;
appearance.SetVisibleSignature(name);
appearance.Contact = contact;
appearance.SignDate = signDate;
MySignatureEvent eEvent = new MySignatureEvent();
eEvent.FullName = fullName;
appearance.SignatureEvent = eEvent;
// Creating the signature
IExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm);
MakeSignature.SignDetached(appearance, pks, chain, null, null, null, 0, subfilter);
}
static void Main(string[] args) {
Pkcs12Store store = new Pkcs12Store(new FileStream(KEYSTORE, FileMode.Open), PASSWORD);
String alias = "";
ICollection<X509Certificate> chain = new List<X509Certificate>();
// searching for private key
foreach (string al in store.Aliases)
if (store.IsKeyEntry(al) && store.GetKey(al).Key.IsPrivate) {
alias = al;
break;
}
AsymmetricKeyEntry pk = store.GetKey(alias);
foreach (X509CertificateEntry c in store.GetCertificateChain(alias))
chain.Add(c.Certificate);
RsaPrivateCrtKeyParameters parameters = pk.Key as RsaPrivateCrtKeyParameters;
C2_08_SignatureMetadata app = new C2_08_SignatureMetadata();
app.Sign(SRC, "Signature1", String.Format(DEST, 1), chain, parameters, DigestAlgorithms.SHA256,
CryptoStandard.CMS, "Appearance 1", "Ghent", "555 123 456", new DateTime(2012, 8, 5), "Bruno L. Specimen");
}
}
}
c2_09_signaturetypes
JAVA
JAVA
/*
* 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
*/
package signatures.chapter2;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Security;
import java.security.cert.Certificate;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.PdfAnnotation;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfSignatureAppearance;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.security.BouncyCastleDigest;
import com.itextpdf.text.pdf.security.DigestAlgorithms;
import com.itextpdf.text.pdf.security.ExternalDigest;
import com.itextpdf.text.pdf.security.ExternalSignature;
import com.itextpdf.text.pdf.security.MakeSignature;
import com.itextpdf.text.pdf.security.MakeSignature.CryptoStandard;
import com.itextpdf.text.pdf.security.PrivateKeySignature;
public class C2_09_SignatureTypes {
public static final String KEYSTORE = "src/main/resources/ks";
public static final char[] PASSWORD = "password".toCharArray();
public static final String SRC = "src/main/resources/hello.pdf";
public static final String DEST = "results/chapter2/hello_level_%s.pdf";
public void sign(String src, String dest,
Certificate[] chain, PrivateKey pk,
String digestAlgorithm, String provider,
CryptoStandard subfilter, int certificationLevel,
String reason, String location)
throws GeneralSecurityException, IOException, DocumentException {
// Creating the reader and the stamper
PdfReader reader = new PdfReader(src);
FileOutputStream os = new FileOutputStream(dest);
PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0');
// Creating the appearance
PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
appearance.setReason(reason);
appearance.setLocation(location);
appearance.setVisibleSignature(new Rectangle(36, 748, 144, 780), 1, "sig");
appearance.setCertificationLevel(certificationLevel);
// Creating the signature
ExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm, provider);
ExternalDigest digest = new BouncyCastleDigest();
MakeSignature.signDetached(appearance, digest, pks, chain, null, null, null, 0, subfilter);
}
public void addText(String src, String dest) throws IOException, DocumentException {
PdfReader reader = new PdfReader(src);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest), '\0', true);
ColumnText.showTextAligned(stamper.getOverContent(1), Element.ALIGN_LEFT, new Phrase("TOP SECRET"), 36, 820, 0);
stamper.close();
}
public void addAnnotation(String src, String dest) throws IOException, DocumentException {
PdfReader reader = new PdfReader(src);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest), '\0', true);
PdfAnnotation comment = PdfAnnotation.createText(stamper.getWriter(),
new Rectangle(200, 800, 250, 820), "Finally Signed!",
"Bruno Specimen has finally signed the document", true, "Comment");
stamper.addAnnotation(comment, 1);
stamper.close();
}
public void addWrongAnnotation(String src, String dest) throws IOException, DocumentException {
PdfReader reader = new PdfReader(src);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
PdfAnnotation comment = PdfAnnotation.createText(stamper.getWriter(),
new Rectangle(200, 800, 250, 820), "Finally Signed!",
"Bruno Specimen has finally signed the document", true, "Comment");
stamper.addAnnotation(comment, 1);
stamper.close();
}
public void signAgain(String src, String dest, Certificate[] chain, PrivateKey pk,
String digestAlgorithm, String provider,
CryptoStandard subfilter,
String reason, String location)
throws GeneralSecurityException, IOException, DocumentException {
// Creating the reader and the stamper
PdfReader reader = new PdfReader(src);
FileOutputStream os = new FileOutputStream(dest);
PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0', null, true);
// Creating the appearance
PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
appearance.setReason(reason);
appearance.setLocation(location);
appearance.setVisibleSignature(new Rectangle(36, 700, 144, 732), 1, "Signature2");
// Creating the signature
ExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm, provider);
ExternalDigest digest = new BouncyCastleDigest();
MakeSignature.signDetached(appearance, digest, pks, chain, null, null, null, 0, subfilter);
}
public static void main(String[] args) throws GeneralSecurityException, IOException, DocumentException {
BouncyCastleProvider provider = new BouncyCastleProvider();
Security.addProvider(provider);
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(new FileInputStream(KEYSTORE), PASSWORD);
String alias = (String)ks.aliases().nextElement();
PrivateKey pk = (PrivateKey) ks.getKey(alias, PASSWORD);
Certificate[] chain = ks.getCertificateChain(alias);
C2_09_SignatureTypes app = new C2_09_SignatureTypes();
app.sign(SRC, String.format(DEST, 1), chain, pk, DigestAlgorithms.SHA256, provider.getName(), CryptoStandard.CMS, PdfSignatureAppearance.NOT_CERTIFIED, "Test 1", "Ghent");
app.sign(SRC, String.format(DEST, 2), chain, pk, DigestAlgorithms.SHA256, provider.getName(), CryptoStandard.CMS, PdfSignatureAppearance.CERTIFIED_FORM_FILLING_AND_ANNOTATIONS, "Test 1", "Ghent");
app.sign(SRC, String.format(DEST, 3), chain, pk, DigestAlgorithms.SHA256, provider.getName(), CryptoStandard.CMS, PdfSignatureAppearance.CERTIFIED_FORM_FILLING, "Test 1", "Ghent");
app.sign(SRC, String.format(DEST, 4), chain, pk, DigestAlgorithms.SHA256, provider.getName(), CryptoStandard.CMS, PdfSignatureAppearance.CERTIFIED_NO_CHANGES_ALLOWED, "Test 1", "Ghent");
app.addWrongAnnotation(String.format(DEST, 1), String.format(DEST, "1_annotated_wrong"));
app.addAnnotation(String.format(DEST, 1), String.format(DEST, "1_annotated"));
app.addAnnotation(String.format(DEST, 2), String.format(DEST, "2_annotated"));
app.addAnnotation(String.format(DEST, 3), String.format(DEST, "3_annotated"));
app.addAnnotation(String.format(DEST, 4), String.format(DEST, "4_annotated"));
app.addText(String.format(DEST, 1), String.format(DEST, "1_text"));
app.signAgain(String.format(DEST, 1), String.format(DEST, "1_double"), chain, pk, DigestAlgorithms.SHA256, provider.getName(), CryptoStandard.CMS, "Second signature test", "Gent");
app.signAgain(String.format(DEST, 2), String.format(DEST, "2_double"), chain, pk, DigestAlgorithms.SHA256, provider.getName(), CryptoStandard.CMS, "Second signature test", "Gent");
app.signAgain(String.format(DEST, 3), String.format(DEST, "3_double"), chain, pk, DigestAlgorithms.SHA256, provider.getName(), CryptoStandard.CMS, "Second signature test", "Gent");
app.signAgain(String.format(DEST, 4), String.format(DEST, "4_double"), chain, pk, DigestAlgorithms.SHA256, provider.getName(), CryptoStandard.CMS, "Second signature test", "Gent");
}
}
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.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.X509;
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.security;
namespace signatures.chapter2 {
class C2_09_SignatureTypes {
public const String KEYSTORE = "../../../../resources/pkcs12";
public static char[] PASSWORD = "password".ToCharArray();
public const String SRC = "../../../../resources/hello.pdf";
public const String DEST = "../../../../results/chapter2/hello_level_{0}.pdf";
public void Sign(String src, String dest, ICollection<X509Certificate> chain, ICipherParameters pk,
String digestAlgorithm, CryptoStandard subfilter, int certificationLevel, String reason, String location) {
// Creating the reader and the stamper
PdfReader reader = new PdfReader(src);
FileStream os = new FileStream(dest, FileMode.Create);
PdfStamper stamper = PdfStamper.CreateSignature(reader, os, '\0');
// Creating the appearance
PdfSignatureAppearance appearance = stamper.SignatureAppearance;
appearance.Reason = reason;
appearance.Location = location;
appearance.SetVisibleSignature(new Rectangle(36, 748, 144, 780), 1, "sig");
appearance.CertificationLevel = certificationLevel;
// Creating the signature
IExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm);
MakeSignature.SignDetached(appearance, pks, chain, null, null, null, 0, subfilter);
}
public void AddText(String src, String dest) {
PdfReader reader = new PdfReader(src);
PdfStamper stamper = new PdfStamper(reader, new FileStream(dest, FileMode.Create), '\0', true);
ColumnText.ShowTextAligned(stamper.GetOverContent(1), Element.ALIGN_LEFT, new Phrase("TOP SECRET"), 36, 820, 0);
stamper.Close();
}
public void AddAnnotation(String src, String dest) {
PdfReader reader = new PdfReader(src);
PdfStamper stamper = new PdfStamper(reader, new FileStream(dest, FileMode.Create), '\0', true);
PdfAnnotation comment = PdfAnnotation.CreateText(stamper.Writer,
new Rectangle(200, 800, 250, 820), "Finally Signed!",
"Bruno Specimen has finally signed the document", true, "Comment");
stamper.AddAnnotation(comment, 1);
stamper.Close();
}
public void AddWrongAnnotation(String src, String dest) {
PdfReader reader = new PdfReader(src);
PdfStamper stamper = new PdfStamper(reader, new FileStream(dest, FileMode.Create));
PdfAnnotation comment = PdfAnnotation.CreateText(stamper.Writer,
new Rectangle(200, 800, 250, 820), "Finally Signed!",
"Bruno Specimen has finally signed the document", true, "Comment");
stamper.AddAnnotation(comment, 1);
stamper.Close();
}
public void SignAgain(String src, String dest, ICollection<X509Certificate> chain, ICipherParameters pk,
String digestAlgorithm, CryptoStandard subfilter, String reason, String location) {
// Creating the reader and the stamper
PdfReader reader = new PdfReader(src);
FileStream os = new FileStream(dest, FileMode.Create);
PdfStamper stamper = PdfStamper.CreateSignature(reader, os, '\0', null, true);
// Creating the appearance
PdfSignatureAppearance appearance = stamper.SignatureAppearance;
appearance.Reason = reason;
appearance.Location = location;
appearance.SetVisibleSignature(new Rectangle(36, 700, 144, 732), 1, "Signature2");
// Creating the signature
IExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm);
MakeSignature.SignDetached(appearance, pks, chain, null, null, null, 0, subfilter);
}
public static void Main(String[] args) {
Pkcs12Store store = new Pkcs12Store(new FileStream(KEYSTORE, FileMode.Open), PASSWORD);
String alias = "";
ICollection<X509Certificate> chain = new List<X509Certificate>();
// searching for private key
foreach (string al in store.Aliases)
if (store.IsKeyEntry(al) && store.GetKey(al).Key.IsPrivate) {
alias = al;
break;
}
AsymmetricKeyEntry pk = store.GetKey(alias);
foreach (X509CertificateEntry c in store.GetCertificateChain(alias))
chain.Add(c.Certificate);
RsaPrivateCrtKeyParameters parameters = pk.Key as RsaPrivateCrtKeyParameters;
C2_09_SignatureTypes app = new C2_09_SignatureTypes();
app.Sign(SRC, String.Format(DEST, 1), chain, parameters, DigestAlgorithms.SHA256,
CryptoStandard.CMS, PdfSignatureAppearance.NOT_CERTIFIED, "Test 1", "Ghent");
app.Sign(SRC, String.Format(DEST, 2), chain, parameters, DigestAlgorithms.SHA512,
CryptoStandard.CMS, PdfSignatureAppearance.CERTIFIED_FORM_FILLING_AND_ANNOTATIONS, "Test 1", "Ghent");
app.Sign(SRC, String.Format(DEST, 3), chain, parameters, DigestAlgorithms.SHA256,
CryptoStandard.CADES, PdfSignatureAppearance.CERTIFIED_FORM_FILLING, "Test 1", "Ghent");
app.Sign(SRC, String.Format(DEST, 4), chain, parameters, DigestAlgorithms.RIPEMD160,
CryptoStandard.CADES, PdfSignatureAppearance.CERTIFIED_NO_CHANGES_ALLOWED, "Test 1", "Ghent");
app.AddWrongAnnotation(String.Format(DEST, 1), String.Format(DEST, "1_annotated_wrong"));
app.AddAnnotation(String.Format(DEST, 1), String.Format(DEST, "1_annotated"));
app.AddAnnotation(String.Format(DEST, 2), String.Format(DEST, "2_annotated"));
app.AddAnnotation(String.Format(DEST, 3), String.Format(DEST, "3_annotated"));
app.AddAnnotation(String.Format(DEST, 4), String.Format(DEST, "4_annotated"));
app.AddText(String.Format(DEST, 1), String.Format(DEST, "1_text"));
app.SignAgain(String.Format(DEST, 1), String.Format(DEST, "1_double"), chain, parameters, DigestAlgorithms.SHA256,
CryptoStandard.CMS, "Second signature test", "Ghent");
app.SignAgain(String.Format(DEST, 2), String.Format(DEST, "2_double"), chain, parameters, DigestAlgorithms.SHA256,
CryptoStandard.CMS, "Second signature test", "Ghent");
app.SignAgain(String.Format(DEST, 3), String.Format(DEST, "3_double"), chain, parameters, DigestAlgorithms.SHA256,
CryptoStandard.CMS, "Second signature test", "Ghent");
app.SignAgain(String.Format(DEST, 4), String.Format(DEST, "4_double"), chain, parameters, DigestAlgorithms.SHA256,
CryptoStandard.CMS, "Second signature test", "Ghent");
}
}
}
c2_10_sequentialsignatures
JAVA
JAVA
/*
* 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
*/
package signatures.chapter2;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Security;
import java.security.cert.Certificate;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfAnnotation;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfFormField;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPCellEvent;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfSignatureAppearance;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.pdf.security.BouncyCastleDigest;
import com.itextpdf.text.pdf.security.ExternalDigest;
import com.itextpdf.text.pdf.security.ExternalSignature;
import com.itextpdf.text.pdf.security.MakeSignature;
import com.itextpdf.text.pdf.security.MakeSignature.CryptoStandard;
import com.itextpdf.text.pdf.security.PrivateKeySignature;
public class C2_10_SequentialSignatures {
public static final String FORM = "results/chapter2/multiple_signatures.pdf";
public static final String ALICE = "src/main/resources/alice";
public static final String BOB = "src/main/resources/bob";
public static final String CAROL = "src/main/resources/carol";
public static final char[] PASSWORD = "password".toCharArray();
public static final String DEST = "results/chapter2/signed_by_%s.pdf";
public void createForm() throws IOException, DocumentException {
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(FORM));
document.open();
PdfPTable table = new PdfPTable(1);
table.setWidthPercentage(100);
table.addCell("Signer 1: Alice");
table.addCell(createSignatureFieldCell(writer, "sig1"));
table.addCell("Signer 2: Bob");
table.addCell(createSignatureFieldCell(writer, "sig2"));
table.addCell("Signer 3: Carol");
table.addCell(createSignatureFieldCell(writer, "sig3"));
document.add(table);
document.close();
}
protected PdfPCell createSignatureFieldCell(PdfWriter writer, String name) {
PdfPCell cell = new PdfPCell();
cell.setMinimumHeight(50);
PdfFormField field = PdfFormField.createSignature(writer);
field.setFieldName(name);
field.setFlags(PdfAnnotation.FLAGS_PRINT);
cell.setCellEvent(new MySignatureFieldEvent(field));
return cell;
}
public class MySignatureFieldEvent implements PdfPCellEvent {
public PdfFormField field;
public MySignatureFieldEvent(PdfFormField field) {
this.field = field;
}
public void cellLayout(PdfPCell cell, Rectangle position,
PdfContentByte[] canvases) {
PdfWriter writer = canvases[0].getPdfWriter();
field.setPage();
field.setWidget(position, PdfAnnotation.HIGHLIGHT_INVERT);
writer.addAnnotation(field);
}
}
public void sign(String keystore, int level,
String src, String name, String dest)
throws GeneralSecurityException, IOException, DocumentException {
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(new FileInputStream(keystore), PASSWORD);
String alias = (String)ks.aliases().nextElement();
PrivateKey pk = (PrivateKey) ks.getKey(alias, PASSWORD);
Certificate[] chain = ks.getCertificateChain(alias);
// Creating the reader and the stamper
PdfReader reader = new PdfReader(src);
FileOutputStream os = new FileOutputStream(dest);
PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0', null, true);
// Creating the appearance
PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
appearance.setVisibleSignature(name);
appearance.setCertificationLevel(level);
// Creating the signature
ExternalSignature pks = new PrivateKeySignature(pk, "SHA-256", "BC");
ExternalDigest digest = new BouncyCastleDigest();
MakeSignature.signDetached(appearance, digest, pks, chain, null, null, null, 0, CryptoStandard.CMS);
}
public static void main(String[] args) throws IOException, DocumentException, GeneralSecurityException {
BouncyCastleProvider provider = new BouncyCastleProvider();
Security.addProvider(provider);
C2_10_SequentialSignatures app = new C2_10_SequentialSignatures();
app.createForm();
app.sign(ALICE, PdfSignatureAppearance.CERTIFIED_FORM_FILLING, FORM, "sig1", String.format(DEST, "alice"));
app.sign(BOB, PdfSignatureAppearance.NOT_CERTIFIED, String.format(DEST, "alice"), "sig2", String.format(DEST, "bob"));
app.sign(CAROL, PdfSignatureAppearance.NOT_CERTIFIED, String.format(DEST, "bob"), "sig3", String.format(DEST, "carol"));
app.sign(ALICE, PdfSignatureAppearance.NOT_CERTIFIED, FORM, "sig1", String.format(DEST, "alice2"));
app.sign(BOB, PdfSignatureAppearance.NOT_CERTIFIED, String.format(DEST, "alice2"), "sig2", String.format(DEST, "bob2"));
app.sign(CAROL, PdfSignatureAppearance.CERTIFIED_FORM_FILLING, String.format(DEST, "bob2"), "sig3", String.format(DEST, "carol2"));
app.sign(ALICE, PdfSignatureAppearance.NOT_CERTIFIED, FORM, "sig1", String.format(DEST, "alice3"));
app.sign(BOB, PdfSignatureAppearance.NOT_CERTIFIED, String.format(DEST, "alice3"), "sig2", String.format(DEST, "bob3"));
app.sign(CAROL, PdfSignatureAppearance.CERTIFIED_NO_CHANGES_ALLOWED, String.format(DEST, "bob3"), "sig3", String.format(DEST, "carol3"));
app.sign(ALICE, PdfSignatureAppearance.CERTIFIED_FORM_FILLING, FORM, "sig1", String.format(DEST, "alice4"));
app.sign(BOB, PdfSignatureAppearance.NOT_CERTIFIED, String.format(DEST, "alice4"), "sig2", String.format(DEST, "bob4"));
app.sign(CAROL, PdfSignatureAppearance.CERTIFIED_FORM_FILLING, String.format(DEST, "bob4"), "sig3", String.format(DEST, "carol4"));
}
}
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.Crypto.Parameters;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.X509;
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.security;
namespace signatures.chapter2 {
class C2_10_SequentialSignatures {
public const String FORM = "../../../../results/chapter2/multiple_signatures.pdf";
public const String ALICE = "../../../../resources/alice";
public const String BOB = "../../../../resources/bob";
public const String CAROL = "../../../../resources/carol";
public static char[] PASSWORD = "password".ToCharArray();
public const String DEST = "../../../../results/chapter2/signed_by_{0}.pdf";
public void CreateForm() {
Document document = new Document();
PdfWriter writer = PdfWriter.GetInstance(document, new FileStream(FORM, FileMode.Create));
document.Open();
PdfPTable table = new PdfPTable(1);
table.WidthPercentage = 100;
table.AddCell("Signer 1: Alice");
table.AddCell(CreateSignatureFieldCell(writer, "sig1"));
table.AddCell("Signer 2: Bob");
table.AddCell(CreateSignatureFieldCell(writer, "sig2"));
table.AddCell("Signer 3: Carol");
table.AddCell(CreateSignatureFieldCell(writer, "sig3"));
document.Add(table);
document.Close();
}
protected PdfPCell CreateSignatureFieldCell(PdfWriter writer, String name) {
PdfPCell cell = new PdfPCell();
cell.MinimumHeight = 50;
PdfFormField field = PdfFormField.CreateSignature(writer);
field.FieldName = name;
field.Flags = PdfAnnotation.FLAGS_PRINT;
cell.CellEvent = new MySignatureFieldEvent(field);
return cell;
}
public class MySignatureFieldEvent : IPdfPCellEvent {
public PdfFormField field;
public MySignatureFieldEvent(PdfFormField field) {
this.field = field;
}
public void CellLayout(PdfPCell cell, Rectangle position, PdfContentByte[] canvases) {
PdfWriter writer = canvases[0].PdfWriter;
field.SetPage();
field.SetWidget(position, PdfAnnotation.HIGHLIGHT_INVERT);
writer.AddAnnotation(field);
}
}
public void Sign(String keystore, int level, String src, String name, String dest) {
Pkcs12Store store = new Pkcs12Store(new FileStream(keystore, FileMode.Open), PASSWORD);
String alias = "";
ICollection<X509Certificate> chain = new List<X509Certificate>();
// searching for private key
foreach (string al in store.Aliases)
if (store.IsKeyEntry(al) && store.GetKey(al).Key.IsPrivate) {
alias = al;
break;
}
AsymmetricKeyEntry pk = store.GetKey(alias);
foreach (X509CertificateEntry c in store.GetCertificateChain(alias))
chain.Add(c.Certificate);
RsaPrivateCrtKeyParameters parameters = pk.Key as RsaPrivateCrtKeyParameters;
PdfReader reader = new PdfReader(src);
FileStream os = new FileStream(dest, FileMode.Create);
PdfStamper stamper = PdfStamper.CreateSignature(reader, os, '\0', null, true);
// Creating the appearance
PdfSignatureAppearance appearance = stamper.SignatureAppearance;
appearance.SetVisibleSignature(name);
appearance.CertificationLevel = level;
// Creating the signature
IExternalSignature pks = new PrivateKeySignature(parameters, "SHA-256");
MakeSignature.SignDetached(appearance, pks, chain, null, null, null, 0, CryptoStandard.CMS);
}
static void Main(string[] args) {
C2_10_SequentialSignatures app = new C2_10_SequentialSignatures();
app.CreateForm();
app.Sign(ALICE, PdfSignatureAppearance.CERTIFIED_FORM_FILLING, FORM, "sig1", String.Format(DEST, "alice"));
app.Sign(BOB, PdfSignatureAppearance.NOT_CERTIFIED, String.Format(DEST, "alice"), "sig2", String.Format(DEST, "bob"));
app.Sign(CAROL, PdfSignatureAppearance.NOT_CERTIFIED, String.Format(DEST, "bob"), "sig3", String.Format(DEST, "carol"));
app.Sign(ALICE, PdfSignatureAppearance.NOT_CERTIFIED, FORM, "sig1", String.Format(DEST, "alice2"));
app.Sign(BOB, PdfSignatureAppearance.NOT_CERTIFIED, String.Format(DEST, "alice2"), "sig2", String.Format(DEST, "bob2"));
app.Sign(CAROL, PdfSignatureAppearance.CERTIFIED_FORM_FILLING, String.Format(DEST, "bob2"), "sig3", String.Format(DEST, "carol2"));
app.Sign(ALICE, PdfSignatureAppearance.NOT_CERTIFIED, FORM, "sig1", String.Format(DEST, "alice3"));
app.Sign(BOB, PdfSignatureAppearance.NOT_CERTIFIED, String.Format(DEST, "alice3"), "sig2", String.Format(DEST, "bob3"));
app.Sign(CAROL, PdfSignatureAppearance.CERTIFIED_NO_CHANGES_ALLOWED, String.Format(DEST, "bob3"), "sig3", String.Format(DEST, "carol3"));
app.Sign(ALICE, PdfSignatureAppearance.CERTIFIED_FORM_FILLING, FORM, "sig1", String.Format(DEST, "alice4"));
app.Sign(BOB, PdfSignatureAppearance.NOT_CERTIFIED, String.Format(DEST, "alice4"), "sig2", String.Format(DEST, "bob4"));
app.Sign(CAROL, PdfSignatureAppearance.CERTIFIED_FORM_FILLING, String.Format(DEST, "bob4"), "sig3", String.Format(DEST, "carol4"));
}
}
}
c2_11_signatureworkflow
JAVA
JAVA
/*
* 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
*/
package signatures.chapter2;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Security;
import java.security.cert.Certificate;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.ExceptionConverter;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.AcroFields;
import com.itextpdf.text.pdf.PdfAnnotation;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfFormField;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPCellEvent;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfSignatureAppearance;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.pdf.TextField;
import com.itextpdf.text.pdf.security.BouncyCastleDigest;
import com.itextpdf.text.pdf.security.ExternalDigest;
import com.itextpdf.text.pdf.security.ExternalSignature;
import com.itextpdf.text.pdf.security.MakeSignature;
import com.itextpdf.text.pdf.security.MakeSignature.CryptoStandard;
import com.itextpdf.text.pdf.security.PrivateKeySignature;
public class C2_11_SignatureWorkflow {
public static final String FORM = "results/chapter2/form.pdf";
public static final String ALICE = "src/main/resources/alice";
public static final String BOB = "src/main/resources/bob";
public static final String CAROL = "src/main/resources/carol";
public static final String DAVE = "src/main/resources/dave";
public static final char[] PASSWORD = "password".toCharArray();
public static final String DEST = "results/chapter2/step%s_signed_by_%s.pdf";
public class MyTextFieldEvent implements PdfPCellEvent {
public String name;
public MyTextFieldEvent(String name) {
this.name = name;
}
public void cellLayout(PdfPCell cell, Rectangle position,
PdfContentByte[] canvases) {
PdfWriter writer = canvases[0].getPdfWriter();
TextField text = new TextField(writer, position, name);
try {
writer.addAnnotation(text.getTextField());
} catch (IOException e) {
throw new ExceptionConverter(e);
} catch (DocumentException e) {
throw new ExceptionConverter(e);
}
}
}
public class MySignatureFieldEvent implements PdfPCellEvent {
public PdfFormField field;
public MySignatureFieldEvent(PdfFormField field) {
this.field = field;
}
public void cellLayout(PdfPCell cell, Rectangle position,
PdfContentByte[] canvases) {
PdfWriter writer = canvases[0].getPdfWriter();
field.setPage();
field.setWidget(position, PdfAnnotation.HIGHLIGHT_INVERT);
writer.addAnnotation(field);
}
}
public void createForm() throws IOException, DocumentException {
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(FORM));
document.open();
PdfPTable table = new PdfPTable(1);
table.setWidthPercentage(100);
table.addCell("Written by Alice");
table.addCell(createSignatureFieldCell(writer, "sig1"));
table.addCell("For approval by Bob");
table.addCell(createTextFieldCell("approved_bob"));
table.addCell(createSignatureFieldCell(writer, "sig2"));
table.addCell("For approval by Carol");
table.addCell(createTextFieldCell("approved_carol"));
table.addCell(createSignatureFieldCell(writer, "sig3"));
table.addCell("For approval by Dave");
table.addCell(createTextFieldCell("approved_dave"));
table.addCell(createSignatureFieldCell(writer, "sig4"));
document.add(table);
document.close();
}
protected PdfPCell createTextFieldCell(String name) {
PdfPCell cell = new PdfPCell();
cell.setMinimumHeight(20);
cell.setCellEvent(new MyTextFieldEvent(name));
return cell;
}
protected PdfPCell createSignatureFieldCell(PdfWriter writer, String name) {
PdfPCell cell = new PdfPCell();
cell.setMinimumHeight(50);
PdfFormField field = PdfFormField.createSignature(writer);
field.setFieldName(name);
field.setFlags(PdfAnnotation.FLAGS_PRINT);
cell.setCellEvent(new MySignatureFieldEvent(field));
return cell;
}
public void certify(String keystore,
String src, String name, String dest)
throws GeneralSecurityException, IOException, DocumentException {
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(new FileInputStream(keystore), PASSWORD);
String alias = (String)ks.aliases().nextElement();
PrivateKey pk = (PrivateKey) ks.getKey(alias, PASSWORD);
Certificate[] chain = ks.getCertificateChain(alias);
// Creating the reader and the stamper
PdfReader reader = new PdfReader(src);
FileOutputStream os = new FileOutputStream(dest);
PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0', null, true);
// Creating the appearance
PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
appearance.setVisibleSignature(name);
appearance.setCertificationLevel(PdfSignatureAppearance.CERTIFIED_FORM_FILLING);
// Creating the signature
ExternalSignature pks = new PrivateKeySignature(pk, "SHA-256", "BC");
ExternalDigest digest = new BouncyCastleDigest();
MakeSignature.signDetached(appearance, digest, pks, chain, null, null, null, 0, CryptoStandard.CMS);
}
public void fillOut(String src, String dest, String name, String value) throws IOException, DocumentException {
PdfReader reader = new PdfReader(src);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest), '\0', true);
AcroFields form = stamper.getAcroFields();
form.setField(name, value);
form.setFieldProperty(name, "setfflags", PdfFormField.FF_READ_ONLY, null);
stamper.close();
}
public void sign(String keystore,
String src, String name, String dest)
throws GeneralSecurityException, IOException, DocumentException {
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(new FileInputStream(keystore), PASSWORD);
String alias = (String)ks.aliases().nextElement();
PrivateKey pk = (PrivateKey) ks.getKey(alias, PASSWORD);
Certificate[] chain = ks.getCertificateChain(alias);
// Creating the reader and the stamper
PdfReader reader = new PdfReader(src);
FileOutputStream os = new FileOutputStream(dest);
PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0', null, true);
// Creating the appearance
PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
appearance.setVisibleSignature(name);
// Creating the signature
ExternalSignature pks = new PrivateKeySignature(pk, "SHA-256", "BC");
ExternalDigest digest = new BouncyCastleDigest();
MakeSignature.signDetached(appearance, digest, pks, chain, null, null, null, 0, CryptoStandard.CMS);
}
public void fillOutAndSign(String keystore,
String src, String name, String fname, String value, String dest)
throws GeneralSecurityException, IOException, DocumentException {
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(new FileInputStream(keystore), PASSWORD);
String alias = (String)ks.aliases().nextElement();
PrivateKey pk = (PrivateKey) ks.getKey(alias, PASSWORD);
Certificate[] chain = ks.getCertificateChain(alias);
// Creating the reader and the stamper
PdfReader reader = new PdfReader(src);
FileOutputStream os = new FileOutputStream(dest);
PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0', null, true);
AcroFields form = stamper.getAcroFields();
form.setField(fname, value);
form.setFieldProperty(fname, "setfflags", PdfFormField.FF_READ_ONLY, null);
// Creating the appearance
PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
appearance.setVisibleSignature(name);
// Creating the signature
ExternalSignature pks = new PrivateKeySignature(pk, "SHA-256", "BC");
ExternalDigest digest = new BouncyCastleDigest();
MakeSignature.signDetached(appearance, digest, pks, chain, null, null, null, 0, CryptoStandard.CMS);
}
public static void main(String[] args) throws IOException, DocumentException, GeneralSecurityException {
BouncyCastleProvider provider = new BouncyCastleProvider();
Security.addProvider(provider);
C2_11_SignatureWorkflow app = new C2_11_SignatureWorkflow();
app.createForm();
app.certify(ALICE, FORM, "sig1", String.format(DEST, 1, "alice"));
app.fillOut(String.format(DEST, 1, "alice"), String.format(DEST, 2, "alice_and_filled_out_by_bob"), "approved_bob", "Read and Approved by Bob");
app.sign(BOB, String.format(DEST, 2, "alice_and_filled_out_by_bob"), "sig2", String.format(DEST, 3, "alice_and_bob"));
app.fillOut(String.format(DEST, 3, "alice_and_bob"), String.format(DEST, 4, "alice_and_bob_filled_out_by_carol"), "approved_carol", "Read and Approved by Carol");
app.sign(CAROL, String.format(DEST, 4, "alice_and_bob_filled_out_by_carol"), "sig3", String.format(DEST, 5, "alice_bob_and_carol"));
app.fillOutAndSign(DAVE, String.format(DEST, 5, "alice_bob_and_carol"), "sig4", "approved_dave", "Read and Approved by Dave", String.format(DEST, 6, "alice_bob_carol_and_dave"));
}
}
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.Crypto.Parameters;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.X509;
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.security;
namespace signatures.chapter2 {
class C2_11_SignatureWorkflow {
public const String FORM = "../../../../results/chapter2/form.pdf";
public const String ALICE = "../../../../resources/alice";
public const String BOB = "../../../../resources/bob";
public const String CAROL = "../../../../resources/carol";
public const String DAVE = "../../../../resources/dave";
public static char[] PASSWORD = "password".ToCharArray();
public const String DEST = "../../../../results/chapter2/step{0}_signed_by_{1}.pdf";
public class MyTextFieldEvent : IPdfPCellEvent {
public String name;
public MyTextFieldEvent(String name) {
this.name = name;
}
public void CellLayout(PdfPCell cell, Rectangle position, PdfContentByte[] canvases) {
PdfWriter writer = canvases[0].PdfWriter;
TextField text = new TextField(writer, position, name);
writer.AddAnnotation(text.GetTextField());
}
}
public class MySignatureFieldEvent : IPdfPCellEvent {
public PdfFormField field;
public MySignatureFieldEvent(PdfFormField field) {
this.field = field;
}
public void CellLayout(PdfPCell cell, Rectangle position,
PdfContentByte[] canvases) {
PdfWriter writer = canvases[0].PdfWriter;
field.SetPage();
field.SetWidget(position, PdfAnnotation.HIGHLIGHT_INVERT);
writer.AddAnnotation(field);
}
}
public void CreateForm() {
Document document = new Document();
PdfWriter writer = PdfWriter.GetInstance(document, new FileStream(FORM, FileMode.Create));
document.Open();
PdfPTable table = new PdfPTable(1);
table.WidthPercentage = 100;
table.AddCell("Written by Alice");
table.AddCell(CreateSignatureFieldCell(writer, "sig1"));
table.AddCell("For approval by Bob");
table.AddCell(CreateTextFieldCell("approved_bob"));
table.AddCell(CreateSignatureFieldCell(writer, "sig2"));
table.AddCell("For approval by Carol");
table.AddCell(CreateTextFieldCell("approved_carol"));
table.AddCell(CreateSignatureFieldCell(writer, "sig3"));
table.AddCell("For approval by Dave");
table.AddCell(CreateTextFieldCell("approved_dave"));
table.AddCell(CreateSignatureFieldCell(writer, "sig4"));
document.Add(table);
document.Close();
}
protected PdfPCell CreateTextFieldCell(String name) {
PdfPCell cell = new PdfPCell();
cell.MinimumHeight = 20;
cell.CellEvent = new MyTextFieldEvent(name);
return cell;
}
protected PdfPCell CreateSignatureFieldCell(PdfWriter writer, String name) {
PdfPCell cell = new PdfPCell();
cell.MinimumHeight = 50;
PdfFormField field = PdfFormField.CreateSignature(writer);
field.FieldName = name;
field.Flags = PdfAnnotation.FLAGS_PRINT;
cell.CellEvent = new MySignatureFieldEvent(field);
return cell;
}
public void Certify(String keystore, String src, String name, String dest) {
Pkcs12Store store = new Pkcs12Store(new FileStream(keystore, FileMode.Open), PASSWORD);
String alias = "";
ICollection<X509Certificate> chain = new List<X509Certificate>();
// searching for private key
foreach (string al in store.Aliases)
if (store.IsKeyEntry(al) && store.GetKey(al).Key.IsPrivate) {
alias = al;
break;
}
AsymmetricKeyEntry pk = store.GetKey(alias);
foreach (X509CertificateEntry c in store.GetCertificateChain(alias))
chain.Add(c.Certificate);
RsaPrivateCrtKeyParameters parameters = pk.Key as RsaPrivateCrtKeyParameters;
PdfReader reader = new PdfReader(src);
FileStream os = new FileStream(dest, FileMode.Create);
PdfStamper stamper = PdfStamper.CreateSignature(reader, os, '\0', null, true);
// Creating the appearance
PdfSignatureAppearance appearance = stamper.SignatureAppearance;
appearance.SetVisibleSignature(name);
appearance.CertificationLevel = PdfSignatureAppearance.CERTIFIED_FORM_FILLING;
// Creating the signature
IExternalSignature pks = new PrivateKeySignature(parameters, "SHA-256");
MakeSignature.SignDetached(appearance, pks, chain, null, null, null, 0, CryptoStandard.CMS);
}
public void FillOut(String src, String dest, String name, String value) {
PdfReader reader = new PdfReader(src);
PdfStamper stamper = new PdfStamper(reader, new FileStream(dest, FileMode.Create), '\0', true);
AcroFields form = stamper.AcroFields;
form.SetField(name, value);
form.SetFieldProperty(name, "setfflags", PdfFormField.FF_READ_ONLY, null);
stamper.Close();
}
public void Sign(String keystore, String src, String name, String dest) {
Pkcs12Store store = new Pkcs12Store(new FileStream(keystore, FileMode.Open), PASSWORD);
String alias = "";
ICollection<X509Certificate> chain = new List<X509Certificate>();
// searching for private key
foreach (string al in store.Aliases)
if (store.IsKeyEntry(al) && store.GetKey(al).Key.IsPrivate) {
alias = al;
break;
}
AsymmetricKeyEntry pk = store.GetKey(alias);
foreach (X509CertificateEntry c in store.GetCertificateChain(alias))
chain.Add(c.Certificate);
RsaPrivateCrtKeyParameters parameters = pk.Key as RsaPrivateCrtKeyParameters;
PdfReader reader = new PdfReader(src);
FileStream os = new FileStream(dest, FileMode.Create);
PdfStamper stamper = PdfStamper.CreateSignature(reader, os, '\0', null, true);
// Creating the appearance
PdfSignatureAppearance appearance = stamper.SignatureAppearance;
appearance.SetVisibleSignature(name);
// Creating the signature
IExternalSignature pks = new PrivateKeySignature(parameters, "SHA-256");
MakeSignature.SignDetached(appearance, pks, chain, null, null, null, 0, CryptoStandard.CMS);
}
public void FillOutAndSign(String keystore, String src, String name, String fname, String value, String dest) {
Pkcs12Store store = new Pkcs12Store(new FileStream(keystore, FileMode.Open), PASSWORD);
String alias = "";
ICollection<X509Certificate> chain = new List<X509Certificate>();
// searching for private key
foreach (string al in store.Aliases)
if (store.IsKeyEntry(al) && store.GetKey(al).Key.IsPrivate) {
alias = al;
break;
}
AsymmetricKeyEntry pk = store.GetKey(alias);
foreach (X509CertificateEntry c in store.GetCertificateChain(alias))
chain.Add(c.Certificate);
RsaPrivateCrtKeyParameters parameters = pk.Key as RsaPrivateCrtKeyParameters;
PdfReader reader = new PdfReader(src);
FileStream os = new FileStream(dest, FileMode.Create);
PdfStamper stamper = PdfStamper.CreateSignature(reader, os, '\0', null, true);
AcroFields form = stamper.AcroFields;
form.SetField(fname, value);
form.SetFieldProperty(fname, "setfflags", PdfFormField.FF_READ_ONLY, null);
// Creating the appearance
PdfSignatureAppearance appearance = stamper.SignatureAppearance;
appearance.SetVisibleSignature(name);
// Creating the signature
IExternalSignature pks = new PrivateKeySignature(parameters, "SHA-256");
MakeSignature.SignDetached(appearance, pks, chain, null, null, null, 0, CryptoStandard.CMS);
}
public static void Main(String[] args) {
C2_11_SignatureWorkflow app = new C2_11_SignatureWorkflow();
app.CreateForm();
app.Certify(ALICE, FORM, "sig1", String.Format(DEST, 1, "alice"));
app.FillOut(String.Format(DEST, 1, "alice"), String.Format(DEST, 2, "alice_and_filled_out_by_bob"), "approved_bob", "Read and Approved by Bob");
app.Sign(BOB, String.Format(DEST, 2, "alice_and_filled_out_by_bob"), "sig2", String.Format(DEST, 3, "alice_and_bob"));
app.FillOut(String.Format(DEST, 3, "alice_and_bob"), String.Format(DEST, 4, "alice_and_bob_filled_out_by_carol"), "approved_carol", "Read and Approved by Carol");
app.Sign(CAROL, String.Format(DEST, 4, "alice_and_bob_filled_out_by_carol"), "sig3", String.Format(DEST, 5, "alice_bob_and_carol"));
app.FillOutAndSign(DAVE, String.Format(DEST, 5, "alice_bob_and_carol"), "sig4", "approved_dave", "Read and Approved by Dave", String.Format(DEST, 6, "alice_bob_carol_and_dave"));
}
}
}
c2_12_lockfields
JAVA
JAVA
/*
* 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
*/
package signatures.chapter2;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Security;
import java.security.cert.Certificate;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.ExceptionConverter;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.AcroFields;
import com.itextpdf.text.pdf.PdfAnnotation;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfDictionary;
import com.itextpdf.text.pdf.PdfFormField;
import com.itextpdf.text.pdf.PdfName;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPCellEvent;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfSigLockDictionary;
import com.itextpdf.text.pdf.PdfSigLockDictionary.LockAction;
import com.itextpdf.text.pdf.PdfSigLockDictionary.LockPermissions;
import com.itextpdf.text.pdf.PdfSignatureAppearance;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.pdf.TextField;
import com.itextpdf.text.pdf.security.BouncyCastleDigest;
import com.itextpdf.text.pdf.security.DigestAlgorithms;
import com.itextpdf.text.pdf.security.ExternalDigest;
import com.itextpdf.text.pdf.security.MakeSignature;
import com.itextpdf.text.pdf.security.MakeSignature.CryptoStandard;
import com.itextpdf.text.pdf.security.PrivateKeySignature;
public class C2_12_LockFields {
public static final String FORM = "results/chapter2/form_lock.pdf";
public static final String ALICE = "src/main/resources/alice";
public static final String BOB = "src/main/resources/bob";
public static final String CAROL = "src/main/resources/carol";
public static final String DAVE = "src/main/resources/dave";
public static final char[] PASSWORD = "password".toCharArray();
public static final String DEST = "results/chapter2/step_%s_signed_by_%s.pdf";
public class MyTextFieldEvent implements PdfPCellEvent {
public String name;
public MyTextFieldEvent(String name) {
this.name = name;
}
public void cellLayout(PdfPCell cell, Rectangle position,
PdfContentByte[] canvases) {
PdfWriter writer = canvases[0].getPdfWriter();
TextField text = new TextField(writer, position, name);
try {
writer.addAnnotation(text.getTextField());
} catch (IOException e) {
throw new ExceptionConverter(e);
} catch (DocumentException e) {
throw new ExceptionConverter(e);
}
}
}
public class MySignatureFieldEvent implements PdfPCellEvent {
public PdfFormField field;
public MySignatureFieldEvent(PdfFormField field) {
this.field = field;
}
public void cellLayout(PdfPCell cell, Rectangle position,
PdfContentByte[] canvases) {
PdfWriter writer = canvases[0].getPdfWriter();
field.setPage();
field.setWidget(position, PdfAnnotation.HIGHLIGHT_INVERT);
writer.addAnnotation(field);
}
}
public void createForm() throws IOException, DocumentException {
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(FORM));
document.open();
PdfPTable table = new PdfPTable(1);
table.setWidthPercentage(100);
table.addCell("Written by Alice");
table.addCell(createSignatureFieldCell(writer, "sig1", null));
table.addCell("For approval by Bob");
table.addCell(createTextFieldCell("approved_bob"));
PdfSigLockDictionary lock = new PdfSigLockDictionary(LockAction.INCLUDE, "sig1", "approved_bob", "sig2");
table.addCell(createSignatureFieldCell(writer, "sig2", lock));
table.addCell("For approval by Carol");
table.addCell(createTextFieldCell("approved_carol"));
lock = new PdfSigLockDictionary(LockAction.EXCLUDE, "approved_dave", "sig4");
table.addCell(createSignatureFieldCell(writer, "sig3", lock));
table.addCell("For approval by Dave");
table.addCell(createTextFieldCell("approved_dave"));
lock = new PdfSigLockDictionary(LockPermissions.NO_CHANGES_ALLOWED);
table.addCell(createSignatureFieldCell(writer, "sig4", lock));
document.add(table);
document.close();
}
protected PdfPCell createTextFieldCell(String name) {
PdfPCell cell = new PdfPCell();
cell.setMinimumHeight(20);
cell.setCellEvent(new MyTextFieldEvent(name));
return cell;
}
protected PdfPCell createSignatureFieldCell(PdfWriter writer, String name, PdfDictionary lock) throws IOException {
PdfPCell cell = new PdfPCell();
cell.setMinimumHeight(50);
PdfFormField field = PdfFormField.createSignature(writer);
field.setFieldName(name);
if (lock != null)
field.put(PdfName.LOCK, writer.addToBody(lock).getIndirectReference());
field.setFlags(PdfAnnotation.FLAGS_PRINT);
cell.setCellEvent(new MySignatureFieldEvent(field));
return cell;
}
public void certify(String keystore,
String src, String name, String dest)
throws GeneralSecurityException, IOException, DocumentException {
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(new FileInputStream(keystore), PASSWORD);
String alias = (String)ks.aliases().nextElement();
PrivateKey pk = (PrivateKey) ks.getKey(alias, PASSWORD);
Certificate[] chain = ks.getCertificateChain(alias);
// Creating the reader and the stamper
PdfReader reader = new PdfReader(src);
FileOutputStream os = new FileOutputStream(dest);
PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0', null, true);
// Creating the appearance
PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
appearance.setVisibleSignature(name);
appearance.setCertificationLevel(PdfSignatureAppearance.CERTIFIED_FORM_FILLING);
AcroFields form = stamper.getAcroFields();
form.setFieldProperty(name, "setfflags", PdfFormField.FF_READ_ONLY, null);
// Creating the signature
PrivateKeySignature pks = new PrivateKeySignature(pk, DigestAlgorithms.SHA256, "BC");
ExternalDigest digest = new BouncyCastleDigest();
MakeSignature.signDetached(appearance, digest, pks, chain, null, null, null, 0, CryptoStandard.CMS);
}
public void fillOutAndSign(String keystore,
String src, String name, String fname, String value, String dest)
throws GeneralSecurityException, IOException, DocumentException {
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(new FileInputStream(keystore), PASSWORD);
String alias = (String)ks.aliases().nextElement();
PrivateKey pk = (PrivateKey) ks.getKey(alias, PASSWORD);
Certificate[] chain = ks.getCertificateChain(alias);
// Creating the reader and the stamper
PdfReader reader = new PdfReader(src);
FileOutputStream os = new FileOutputStream(dest);
PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0', null, true);
AcroFields form = stamper.getAcroFields();
form.setField(fname, value);
form.setFieldProperty(name, "setfflags", PdfFormField.FF_READ_ONLY, null);
form.setFieldProperty(fname, "setfflags", PdfFormField.FF_READ_ONLY, null);
// Creating the appearance
PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
appearance.setVisibleSignature(name);
// Creating the signature
PrivateKeySignature pks = new PrivateKeySignature(pk, DigestAlgorithms.SHA256, "BC");
ExternalDigest digest = new BouncyCastleDigest();
MakeSignature.signDetached(appearance, digest, pks, chain, null, null, null, 0, CryptoStandard.CMS);
}
public void fillOut(String src, String dest, String name, String value) throws IOException, DocumentException {
PdfReader reader = new PdfReader(src);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest), '\0', true);
AcroFields form = stamper.getAcroFields();
form.setField(name, value);
stamper.close();
}
public void sign(String keystore,
String src, String name, String dest)
throws GeneralSecurityException, IOException, DocumentException {
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(new FileInputStream(keystore), PASSWORD);
String alias = (String)ks.aliases().nextElement();
PrivateKey pk = (PrivateKey) ks.getKey(alias, PASSWORD);
Certificate[] chain = ks.getCertificateChain(alias);
// Creating the reader and the stamper
PdfReader reader = new PdfReader(src);
FileOutputStream os = new FileOutputStream(dest);
PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0', null, true);
// Creating the appearance
PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
appearance.setVisibleSignature(name);
// Creating the signature
PrivateKeySignature pks = new PrivateKeySignature(pk, DigestAlgorithms.SHA256, "BC");
ExternalDigest digest = new BouncyCastleDigest();
MakeSignature.signDetached(appearance, digest, pks, chain, null, null, null, 0, CryptoStandard.CMS);
}
public static void main(String[] args) throws IOException, DocumentException, GeneralSecurityException {
BouncyCastleProvider provider = new BouncyCastleProvider();
Security.addProvider(provider);
C2_12_LockFields app = new C2_12_LockFields();
app.createForm();
app.certify(ALICE, FORM, "sig1", String.format(DEST, 1, "alice"));
app.fillOutAndSign(BOB, String.format(DEST, 1, "alice"), "sig2", "approved_bob", "Read and Approved by Bob", String.format(DEST, 2, "alice_and_bob"));
app.fillOutAndSign(CAROL, String.format(DEST, 2, "alice_and_bob"), "sig3", "approved_carol", "Read and Approved by Carol", String.format(DEST, 3, "alice_bob_and_carol"));
app.fillOutAndSign(DAVE, String.format(DEST, 3, "alice_bob_and_carol"), "sig4", "approved_dave", "Read and Approved by Dave", String.format(DEST, 4, "alice_bob_carol_and_dave"));
app.fillOut(String.format(DEST, 2, "alice_and_bob"), String.format(DEST, 5, "alice_and_bob_broken_by_chuck"), "approved_bob", "Changed by Chuck");
app.fillOut(String.format(DEST, 4, "alice_bob_carol_and_dave"), String.format(DEST, 6, "dave_broken_by_chuck"), "approved_carol", "Changed by Chuck");
}
}
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.Crypto.Parameters;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.X509;
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.security;
namespace signatures.chapter2 {
class C2_12_LockFields {
public const String FORM = "../../../../results/chapter2/form_lock.pdf";
public const String ALICE = "../../../../resources/alice";
public const String BOB = "../../../../resources/bob";
public const String CAROL = "../../../../resources/carol";
public const String DAVE = "../../../../resources/dave";
public static char[] PASSWORD = "password".ToCharArray();
public const String DEST = "../../../../results/chapter2/step_{0}_signed_by_{1}.pdf";
public class MyTextFieldEvent : IPdfPCellEvent {
public String name;
public MyTextFieldEvent(String name) {
this.name = name;
}
public void CellLayout(PdfPCell cell, Rectangle position, PdfContentByte[] canvases) {
PdfWriter writer = canvases[0].PdfWriter;
TextField text = new TextField(writer, position, name);
writer.AddAnnotation(text.GetTextField());
}
}
public class MySignatureFieldEvent : IPdfPCellEvent {
public PdfFormField field;
public MySignatureFieldEvent(PdfFormField field) {
this.field = field;
}
public void CellLayout(PdfPCell cell, Rectangle position, PdfContentByte[] canvases) {
PdfWriter writer = canvases[0].PdfWriter;
field.SetPage();
field.SetWidget(position, PdfAnnotation.HIGHLIGHT_INVERT);
writer.AddAnnotation(field);
}
}
public void CreateForm() {
Document document = new Document();
PdfWriter writer = PdfWriter.GetInstance(document, new FileStream(FORM, FileMode.Create));
document.Open();
PdfPTable table = new PdfPTable(1);
table.WidthPercentage = 100;
table.AddCell("Written by Alice");
table.AddCell(CreateSignatureFieldCell(writer, "sig1", null));
table.AddCell("For approval by Bob");
table.AddCell(CreateTextFieldCell("approved_bob"));
PdfSigLockDictionary Lock = new PdfSigLockDictionary(PdfSigLockDictionary.LockAction.INCLUDE, "sig1", "approved_bob", "sig2");
table.AddCell(CreateSignatureFieldCell(writer, "sig2", Lock));
table.AddCell("For approval by Carol");
table.AddCell(CreateTextFieldCell("approved_carol"));
Lock = new PdfSigLockDictionary(PdfSigLockDictionary.LockAction.EXCLUDE, "approved_dave", "sig4");
table.AddCell(CreateSignatureFieldCell(writer, "sig3", Lock));
table.AddCell("For approval by Dave");
table.AddCell(CreateTextFieldCell("approved_dave"));
Lock = new PdfSigLockDictionary(PdfSigLockDictionary.LockPermissions.NO_CHANGES_ALLOWED);
table.AddCell(CreateSignatureFieldCell(writer, "sig4", Lock));
document.Add(table);
document.Close();
}
protected PdfPCell CreateTextFieldCell(String name) {
PdfPCell cell = new PdfPCell();
cell.MinimumHeight = 20;
cell.CellEvent = new MyTextFieldEvent(name);
return cell;
}
protected PdfPCell CreateSignatureFieldCell(PdfWriter writer, String name, PdfDictionary Lock) {
PdfPCell cell = new PdfPCell();
cell.MinimumHeight = 50;
PdfFormField field = PdfFormField.CreateSignature(writer);
field.FieldName = name;
if (Lock != null)
field.Put(PdfName.LOCK, writer.AddToBody(Lock).IndirectReference);
field.Flags = PdfAnnotation.FLAGS_PRINT;
cell.CellEvent = new MySignatureFieldEvent(field);
return cell;
}
public void Certify(String keystore, String src, String name, String dest) {
Pkcs12Store store = new Pkcs12Store(new FileStream(keystore, FileMode.Open), PASSWORD);
String alias = "";
ICollection<X509Certificate> chain = new List<X509Certificate>();
// searching for private key
foreach (string al in store.Aliases)
if (store.IsKeyEntry(al) && store.GetKey(al).Key.IsPrivate) {
alias = al;
break;
}
AsymmetricKeyEntry pk = store.GetKey(alias);
foreach (X509CertificateEntry c in store.GetCertificateChain(alias))
chain.Add(c.Certificate);
RsaPrivateCrtKeyParameters parameters = pk.Key as RsaPrivateCrtKeyParameters;
PdfReader reader = new PdfReader(src);
FileStream os = new FileStream(dest, FileMode.Create);
PdfStamper stamper = PdfStamper.CreateSignature(reader, os, '\0', null, true);
// Creating the appearance
PdfSignatureAppearance appearance = stamper.SignatureAppearance;
appearance.SetVisibleSignature(name);
appearance.CertificationLevel = PdfSignatureAppearance.CERTIFIED_FORM_FILLING;
AcroFields form = stamper.AcroFields;
form.SetFieldProperty(name, "setfflags", PdfFormField.FF_READ_ONLY, null);
// Creating the signature
PrivateKeySignature pks = new PrivateKeySignature(parameters, DigestAlgorithms.SHA256);
MakeSignature.SignDetached(appearance, pks, chain, null, null, null, 0, CryptoStandard.CMS);
}
public void FillOutAndSign(String keystore, String src, String name, String fname, String value, String dest) {
Pkcs12Store store = new Pkcs12Store(new FileStream(keystore, FileMode.Open), PASSWORD);
String alias = "";
ICollection<X509Certificate> chain = new List<X509Certificate>();
// searching for private key
foreach (string al in store.Aliases)
if (store.IsKeyEntry(al) && store.GetKey(al).Key.IsPrivate) {
alias = al;
break;
}
AsymmetricKeyEntry pk = store.GetKey(alias);
foreach (X509CertificateEntry c in store.GetCertificateChain(alias))
chain.Add(c.Certificate);
RsaPrivateCrtKeyParameters parameters = pk.Key as RsaPrivateCrtKeyParameters;
PdfReader reader = new PdfReader(src);
FileStream os = new FileStream(dest, FileMode.Create);
PdfStamper stamper = PdfStamper.CreateSignature(reader, os, '\0', null, true);
AcroFields form = stamper.AcroFields;
form.SetField(fname, value);
form.SetFieldProperty(name, "setfflags", PdfFormField.FF_READ_ONLY, null);
form.SetFieldProperty(fname, "setfflags", PdfFormField.FF_READ_ONLY, null);
// Creating the appearance
PdfSignatureAppearance appearance = stamper.SignatureAppearance;
appearance.SetVisibleSignature(name);
// Creating the signature
PrivateKeySignature pks = new PrivateKeySignature(parameters, DigestAlgorithms.SHA256);
MakeSignature.SignDetached(appearance, pks, chain, null, null, null, 0, CryptoStandard.CMS);
}
public void FillOut(String src, String dest, String name, String value) {
PdfReader reader = new PdfReader(src);
PdfStamper stamper = new PdfStamper(reader, new FileStream(dest, FileMode.Create), '\0', true);
AcroFields form = stamper.AcroFields;
form.SetField(name, value);
stamper.Close();
}
public static void Main(String[] args) {
C2_12_LockFields app = new C2_12_LockFields();
app.CreateForm();
app.Certify(ALICE, FORM, "sig1", String.Format(DEST, 1, "alice"));
app.FillOutAndSign(BOB, String.Format(DEST, 1, "alice"), "sig2", "approved_bob", "Read and Approved by Bob", String.Format(DEST, 2, "alice_and_bob"));
app.FillOutAndSign(CAROL, String.Format(DEST, 2, "alice_and_bob"), "sig3", "approved_carol", "Read and Approved by Carol", String.Format(DEST, 3, "alice_bob_and_carol"));
app.FillOutAndSign(DAVE, String.Format(DEST, 3, "alice_bob_and_carol"), "sig4", "approved_dave", "Read and Approved by Dave", String.Format(DEST, 4, "alice_bob_carol_and_dave"));
app.FillOut(String.Format(DEST, 2, "alice_and_bob"), String.Format(DEST, 5, "alice_and_bob_broken_by_chuck"), "approved_bob", "Changed by Chuck");
app.FillOut(String.Format(DEST, 4, "alice_bob_carol_and_dave"), String.Format(DEST, 6, "dave_broken_by_chuck"), "approved_carol", "Changed by Chuck");
}
}
}