Digital signatures - chapter 2

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

1st November 2015
admin-marketing

These examples were written in the context of the white paper Digital Signatures for PDF documents.

C2_01_SignHelloWorld.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
/*
 * 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");
    }
}
C2_02_SignHelloWorldWithTempFile.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
/*
 * 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");
    }
}
C2_03_SignEmptyField.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
/*
 * 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");
    }
}
C2_04_CreateEmptyField.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
/*
 * 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");
    }
}
C2_05_CustomAppearance.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
/*
 * 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");
    }
}
C2_06_SignatureAppearance.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
/*
 * 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");
    }
}
C2_07_SignatureAppearances.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
/*
 * 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);
    }
}
C2_08_SignatureMetadata.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
/*
 * 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");
    }
}
C2_09_SignatureTypes.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/*
 * 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");
    }
}
C2_10_SequentialSignatures.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/*
 * 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"));
    }
}
C2_11_SignatureWorkflow.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
/*
 * 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"));
    }
}
C2_12_LockFields.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
/*
 * 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");
    }
}
C2_01_SignHelloWorld.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
/*
 * 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.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
/*
 * 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.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
/*
 * 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.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
/*
 * 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.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/*
 * 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.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/*
 * 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.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
/*
 * 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.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/*
 * 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.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/*
 * 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.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/*
 * 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.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
/*
 * 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.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
/*
 * 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");
        }
    }
}


Contact

Still have questions? 

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

Contact us
Stay updated

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

Subscribe Now