Digital signatures - chapter 3
These examples were written in the context of Chapter 3 - "Certificate Authorities, certificate revocation and time stamping" of the Digital Signatures for PDF documents eBook.
c3_01_signwithcacert
Signing a document with a PKCS12 file from the CAcert Certificate Authority:
java
package com.itextpdf.samples.signatures.chapter03;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.StampingProperties;
import com.itextpdf.signatures.BouncyCastleDigest;
import com.itextpdf.signatures.ICrlClient;
import com.itextpdf.signatures.DigestAlgorithms;
import com.itextpdf.signatures.IExternalDigest;
import com.itextpdf.signatures.IExternalSignature;
import com.itextpdf.signatures.IOcspClient;
import com.itextpdf.signatures.PdfSignatureAppearance;
import com.itextpdf.signatures.PdfSigner;
import com.itextpdf.signatures.PrivateKeySignature;
import com.itextpdf.signatures.ITSAClient;
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 java.util.Collection;
import java.util.Properties;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
public class C3_01_SignWithCAcert {
public static final String DEST = "./target/signatures/chapter03/";
public static final String SRC = "./src/test/resources/pdfs/hello.pdf";
public static final String[] RESULT_FILES = new String[] {
"hello_cacert.pdf"
};
public void sign(String src, String dest, Certificate[] chain, PrivateKey pk,
String digestAlgorithm, String provider, PdfSigner.CryptoStandard subfilter,
String reason, String location, Collection<ICrlClient> crlList,
IOcspClient ocspClient, ITSAClient tsaClient, int estimatedSize)
throws GeneralSecurityException, IOException {
PdfReader reader = new PdfReader(src);
PdfSigner signer = new PdfSigner(reader, new FileOutputStream(dest), new StampingProperties());
// Create the signature appearance
Rectangle rect = new Rectangle(36, 648, 200, 100);
PdfSignatureAppearance appearance = signer.getSignatureAppearance();
appearance
.setReason(reason)
.setLocation(location)
// Specify if the appearance before field is signed will be used
// as a background for the signed field. The "false" value is the default value.
.setReuseAppearance(false)
.setPageRect(rect)
.setPageNumber(1);
signer.setFieldName("sig");
IExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm, provider);
IExternalDigest digest = new BouncyCastleDigest();
// Sign the document using the detached mode, CMS or CAdES equivalent.
signer.signDetached(digest, pks, chain, crlList, ocspClient, tsaClient, estimatedSize, subfilter);
}
public static void main(String[] args) throws IOException, GeneralSecurityException {
File file = new File(DEST);
file.mkdirs();
Properties properties = new Properties();
/* This properties file should contain a CAcert certificate that belongs to the user,
* according to the original sample purpose. However right now it contains a simple
* self-signed certificate in p12 format, which serves as a stub.
*/
properties.load(new FileInputStream("./src/test/resources/encryption/signkey.properties"));
// Get path to the p12 file
String path = properties.getProperty("PRIVATE");
// Get a password
char[] pass = properties.getProperty("PASSWORD").toCharArray();
BouncyCastleProvider provider = new BouncyCastleProvider();
Security.addProvider(provider);
// The first argument defines that the keys and certificates are stored using PKCS#12
KeyStore ks = KeyStore.getInstance("pkcs12", provider.getName());
ks.load(new FileInputStream(path), pass);
String alias = ks.aliases().nextElement();
PrivateKey pk = (PrivateKey) ks.getKey(alias, pass);
Certificate[] chain = ks.getCertificateChain(alias);
new C3_01_SignWithCAcert().sign(SRC, DEST + RESULT_FILES[0], chain, pk,
DigestAlgorithms.SHA256, provider.getName(), PdfSigner.CryptoStandard.CMS,
"Test", "Ghent", null, null, null, 0);
}
}
C#
using System;
using System.Collections.Generic;
using System.IO;
using iText.Bouncycastle.Cert;
using iText.Bouncycastle.X509;
using iText.Bouncycastle.Crypto;
using iText.Commons.Bouncycastle.Cert;
using iText.Commons.Utils;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.X509;
using iText.Kernel.Geom;
using iText.Kernel.Pdf;
using iText.Signatures;
using Org.BouncyCastle.Pkcs;
namespace iText.Samples.Signatures.Chapter03
{
public class C3_01_SignWithCAcert
{
public static readonly string DEST = "results/signatures/chapter03/";
public static readonly string SRC = "../../../resources/pdfs/hello.pdf";
public static readonly String[] RESULT_FILES =
{
"hello_cacert.pdf"
};
public void Sign(String src, String dest, X509Certificate[] chain, ICipherParameters pk,
String digestAlgorithm, PdfSigner.CryptoStandard subfilter, String reason, String location,
ICollection<ICrlClient> crlList, IOcspClient ocspClient, ITSAClient tsaClient, int estimatedSize)
{
PdfReader reader = new PdfReader(src);
PdfSigner signer = new PdfSigner(reader, new FileStream(dest, FileMode.Create), new StampingProperties());
// Create the signature appearance
Rectangle rect = new Rectangle(36, 648, 200, 100);
PdfSignatureAppearance appearance = signer.GetSignatureAppearance();
appearance
.SetReason(reason)
.SetLocation(location)
// Specify if the appearance before field is signed will be used
// as a background for the signed field. The "false" value is the default value.
.SetReuseAppearance(false)
.SetPageRect(rect)
.SetPageNumber(1);
signer.SetFieldName("sig");
IExternalSignature pks = new PrivateKeySignature(new PrivateKeyBC(pk), digestAlgorithm);
IX509Certificate[] certificateWrappers = new IX509Certificate[chain.Length];
for (int i = 0; i < certificateWrappers.Length; ++i) {
certificateWrappers[i] = new X509CertificateBC(chain[i]);
}
// Sign the document using the detached mode, CMS or CAdES equivalent.
signer.SignDetached(pks, certificateWrappers, crlList, ocspClient, tsaClient, estimatedSize, subfilter);
}
public static void Main(String[] args)
{
DirectoryInfo directory = new DirectoryInfo(DEST);
directory.Create();
Properties properties = new Properties();
/* This properties file should contain a CAcert certificate that belongs to the user,
* according to the original sample purpose. However right now it contains a simple
* self-signed certificate in p12 format, which serves as a stub.
*/
properties.Load(new FileStream("../../../resources/encryption/signkey.properties",
FileMode.Open, FileAccess.Read));
// Get path to the p12 file
String path = properties.GetProperty("PRIVATE");
// Get a password
char[] pass = properties.GetProperty("PASSWORD").ToCharArray();
Pkcs12Store pk12 = new Pkcs12StoreBuilder().Build();
pk12.Load(new FileStream(path, FileMode.Open, FileAccess.Read), pass);
string alias = null;
foreach (var a in pk12.Aliases)
{
alias = ((string) a);
if (pk12.IsKeyEntry(alias))
break;
}
ICipherParameters pk = pk12.GetKey(alias).Key;
X509CertificateEntry[] ce = pk12.GetCertificateChain(alias);
X509Certificate[] chain = new X509Certificate[ce.Length];
for (int k = 0; k < ce.Length; ++k)
{
chain[k] = ce[k].Certificate;
}
new C3_01_SignWithCAcert().Sign(SRC, DEST + RESULT_FILES[0], chain, pk,
DigestAlgorithms.SHA256, PdfSigner.CryptoStandard.CMS,
"Test", "Ghent", null, null, null, 0);
}
}
}
c3_02_getcrlurl
Getting the Certificate Revocation List (CRL) URLs from a certificate chain:
java
package com.itextpdf.samples.signatures.chapter03;
import com.itextpdf.signatures.CertificateUtil;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.Security;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.Properties;
public class C3_02_GetCrlUrl {
public static void main(String[] args) throws IOException, GeneralSecurityException {
Properties properties = new Properties();
// Specify the correct path to the certificate
properties.load(new FileInputStream("c:/home/blowagie/key.properties"));
String path = properties.getProperty("PRIVATE");
char[] pass = properties.getProperty("PASSWORD").toCharArray();
BouncyCastleProvider provider = new BouncyCastleProvider();
Security.addProvider(provider);
KeyStore ks = KeyStore.getInstance("pkcs12", provider.getName());
ks.load(new FileInputStream(path), pass);
String alias = ks.aliases().nextElement();
Certificate[] chain = ks.getCertificateChain(alias);
for (int i = 0; i < chain.length; i++) {
X509Certificate cert = (X509Certificate) chain[i];
System.out.println(String.format("[%s] %s", i, cert.getSubjectDN()));
System.out.println(CertificateUtil.getCRLURL(cert));
}
}
}
C#
using System;
using System.IO;
using iText.Bouncycastle.Cert;
using iText.Bouncycastle.X509;
using iText.Commons.Utils;
using Org.BouncyCastle.X509;
using iText.Signatures;
using Org.BouncyCastle.Pkcs;
namespace iText.Samples.Signatures.Chapter03
{
public class C3_02_GetCrlUrl
{
public static void Main(String[] args)
{
Properties properties = new Properties();
// Specify the correct path to the certificate
properties.Load(new FileStream("c:/home/blowagie/key.properties", FileMode.Open, FileAccess.Read));
String path = properties.GetProperty("PRIVATE");
char[] pass = properties.GetProperty("PASSWORD").ToCharArray();
Pkcs12Store pk12 = new Pkcs12StoreBuilder().Build();
pk12.Load(new FileStream(path, FileMode.Open, FileAccess.Read), pass);
string alias = null;
foreach (var a in pk12.Aliases)
{
alias = ((string) a);
if (pk12.IsKeyEntry(alias))
break;
}
X509CertificateEntry[] ce = pk12.GetCertificateChain(alias);
X509Certificate[] chain = new X509Certificate[ce.Length];
for (int k = 0; k < ce.Length; ++k)
{
chain[k] = ce[k].Certificate;
}
for (int i = 0; i < chain.Length; i++)
{
X509Certificate cert = chain[i];
Console.WriteLine("[{0}] {1}", i, cert.SubjectDN);
Console.WriteLine(CertificateUtil.GetCRLURL(new X509CertificateBC(cert)));
}
}
}
}
c3_03_signwithcrldefaultimp
Using the default CrlClient implementation:
java
package com.itextpdf.samples.signatures.chapter03;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.StampingProperties;
import com.itextpdf.signatures.BouncyCastleDigest;
import com.itextpdf.signatures.ICrlClient;
import com.itextpdf.signatures.CrlClientOnline;
import com.itextpdf.signatures.DigestAlgorithms;
import com.itextpdf.signatures.IExternalDigest;
import com.itextpdf.signatures.IExternalSignature;
import com.itextpdf.signatures.IOcspClient;
import com.itextpdf.signatures.ITSAClient;
import com.itextpdf.signatures.PdfSignatureAppearance;
import com.itextpdf.signatures.PdfSigner;
import com.itextpdf.signatures.PrivateKeySignature;
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 java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Properties;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
public class C3_03_SignWithCRLDefaultImp {
public static final String DEST = "./target/signatures/chapter03/";
public static final String SRC = "./src/test/resources/pdfs/hello.pdf";
public static final String[] RESULT_FILES = new String[] {
"hello_cacert_crl_imp.pdf"
};
public static void main(String[] args) throws IOException, GeneralSecurityException {
File file = new File(DEST);
file.mkdirs();
Properties properties = new Properties();
// Specify the correct path to the certificate
properties.load(new FileInputStream("c:/home/blowagie/key.properties"));
String path = properties.getProperty("PRIVATE");
char[] pass = properties.getProperty("PASSWORD").toCharArray();
BouncyCastleProvider provider = new BouncyCastleProvider();
Security.addProvider(provider);
KeyStore ks = KeyStore.getInstance("pkcs12", provider.getName());
ks.load(new FileInputStream(path), pass);
String alias = ks.aliases().nextElement();
PrivateKey pk = (PrivateKey) ks.getKey(alias, pass);
Certificate[] chain = ks.getCertificateChain(alias);
List<ICrlClient> crlList = new ArrayList<ICrlClient>();
// Add the default implementation of the CrlClientOnline
crlList.add(new CrlClientOnline());
new C3_03_SignWithCRLDefaultImp().sign(SRC, DEST + RESULT_FILES[0], chain, pk, DigestAlgorithms.SHA256,
provider.getName(), PdfSigner.CryptoStandard.CMS, "Test", "Ghent",
crlList, null, null, 0);
}
public void sign(String src, String dest, Certificate[] chain, PrivateKey pk,
String digestAlgorithm, String provider, PdfSigner.CryptoStandard subfilter,
String reason, String location, Collection<ICrlClient> crlList,
IOcspClient ocspClient, ITSAClient tsaClient, int estimatedSize)
throws GeneralSecurityException, IOException {
PdfReader reader = new PdfReader(src);
PdfSigner signer = new PdfSigner(reader, new FileOutputStream(dest), new StampingProperties());
// Create the signature appearance
Rectangle rect = new Rectangle(36, 648, 200, 100);
PdfSignatureAppearance appearance = signer.getSignatureAppearance();
appearance
.setReason(reason)
.setLocation(location)
.setPageRect(rect)
.setPageNumber(1);
signer.setFieldName("sig");
// Creating the signature
IExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm, provider);
IExternalDigest digest = new BouncyCastleDigest();
// Sign the document using the detached mode, CMS or CAdES equivalent.
// Pass the created CRL to the signing method.
signer.signDetached(digest, pks, chain, crlList, ocspClient, tsaClient, estimatedSize, subfilter);
}
}
C#
using System;
using System.Collections.Generic;
using System.IO;
using iText.Bouncycastle.Cert;
using iText.Bouncycastle.X509;
using iText.Bouncycastle.Crypto;
using iText.Commons.Bouncycastle.Cert;
using iText.Commons.Utils;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.X509;
using iText.Kernel.Geom;
using iText.Kernel.Pdf;
using iText.Signatures;
using Org.BouncyCastle.Pkcs;
namespace iText.Samples.Signatures.Chapter03
{
public class C3_03_SignWithCRLDefaultImp
{
public static readonly string DEST = "results/signatures/chapter03/";
public static readonly string SRC = "../../../resources/pdfs/hello.pdf";
public static readonly String[] RESULT_FILES =
{
"hello_cacert_crl_imp.pdf"
};
public static void Main(String[] args)
{
DirectoryInfo directory = new DirectoryInfo(DEST);
directory.Create();
Properties properties = new Properties();
// Specify the correct path to the certificate
properties.Load(new FileStream("c:/home/blowagie/key.properties", FileMode.Open, FileAccess.Read));
String path = properties.GetProperty("PRIVATE");
char[] pass = properties.GetProperty("PASSWORD").ToCharArray();
Pkcs12Store pk12 = new Pkcs12StoreBuilder().Build();
pk12.Load(new FileStream(path, FileMode.Open, FileAccess.Read), pass);
string alias = null;
foreach (var a in pk12.Aliases)
{
alias = ((string) a);
if (pk12.IsKeyEntry(alias))
break;
}
ICipherParameters pk = pk12.GetKey(alias).Key;
X509CertificateEntry[] ce = pk12.GetCertificateChain(alias);
X509Certificate[] chain = new X509Certificate[ce.Length];
for (int k = 0; k < ce.Length; ++k)
{
chain[k] = ce[k].Certificate;
}
IList<ICrlClient> crlList = new List<ICrlClient>();
// Add the default implementation of the CrlClientOnline
crlList.Add(new CrlClientOnline());
new C3_03_SignWithCRLDefaultImp().Sign(SRC, DEST + RESULT_FILES[0], chain, pk,
DigestAlgorithms.SHA256, PdfSigner.CryptoStandard.CMS,
"Test", "Ghent", crlList, null, null, 0);
}
public void Sign(String src, String dest, X509Certificate[] chain, ICipherParameters pk,
String digestAlgorithm, PdfSigner.CryptoStandard subfilter, String reason, String location,
ICollection<ICrlClient> crlList, IOcspClient ocspClient, ITSAClient tsaClient, int estimatedSize)
{
PdfReader reader = new PdfReader(src);
PdfSigner signer = new PdfSigner(reader, new FileStream(dest, FileMode.Create), new StampingProperties());
// Create the signature appearance
Rectangle rect = new Rectangle(36, 648, 200, 100);
PdfSignatureAppearance appearance = signer.GetSignatureAppearance();
appearance
.SetReason(reason)
.SetLocation(location)
// Specify if the appearance before field is signed will be used
// as a background for the signed field. The "false" value is the default value.
.SetReuseAppearance(false)
.SetPageRect(rect)
.SetPageNumber(1);
signer.SetFieldName("sig");
IExternalSignature pks = new PrivateKeySignature(new PrivateKeyBC(pk), digestAlgorithm);
IX509Certificate[] certificateWrappers = new IX509Certificate[chain.Length];
for (int i = 0; i < certificateWrappers.Length; ++i) {
certificateWrappers[i] = new X509CertificateBC(chain[i]);
}
// Sign the document using the detached mode, CMS or CAdES equivalent.
// Pass the created CRL to the signing method.
signer.SignDetached(pks, certificateWrappers, crlList, ocspClient, tsaClient, estimatedSize, subfilter);
}
}
}
c3_04_signwithcrlonline
Getting the CRL online:
java
package com.itextpdf.samples.signatures.chapter03;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.StampingProperties;
import com.itextpdf.signatures.BouncyCastleDigest;
import com.itextpdf.signatures.ICrlClient;
import com.itextpdf.signatures.CrlClientOnline;
import com.itextpdf.signatures.DigestAlgorithms;
import com.itextpdf.signatures.IExternalDigest;
import com.itextpdf.signatures.IExternalSignature;
import com.itextpdf.signatures.IOcspClient;
import com.itextpdf.signatures.ITSAClient;
import com.itextpdf.signatures.PdfSignatureAppearance;
import com.itextpdf.signatures.PdfSigner;
import com.itextpdf.signatures.PrivateKeySignature;
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 java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Properties;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
public class C3_04_SignWithCRLOnline {
public static final String DEST = "./target/signatures/chapter03/";
public static final String SRC = "./src/test/resources/pdfs/hello.pdf";
public static final String[] RESULT_FILES = new String[] {
"hello_cacert_crl.pdf"
};
public static void main(String[] args) throws IOException, GeneralSecurityException {
File file = new File(DEST);
file.mkdirs();
Properties properties = new Properties();
// Specify the correct path to the certificate
properties.load(new FileInputStream("c:/home/blowagie/key.properties"));
String path = properties.getProperty("PRIVATE");
char[] pass = properties.getProperty("PASSWORD").toCharArray();
BouncyCastleProvider provider = new BouncyCastleProvider();
Security.addProvider(provider);
KeyStore ks = KeyStore.getInstance("pkcs12", provider.getName());
ks.load(new FileInputStream(path), pass);
String alias = ks.aliases().nextElement();
PrivateKey pk = (PrivateKey) ks.getKey(alias, pass);
Certificate[] chain = ks.getCertificateChain(alias);
/* Create a CrlClientOnline instance with specified Certificate Revocation List's URL.
* The exact URL for the CRL access point is specific for every CA provider.
* This one is specific for CAcert certificates.
*/
ICrlClient crlClient = new CrlClientOnline("https://crl.cacert.org/revoke.crl");
List<ICrlClient> crlList = new ArrayList<ICrlClient>();
crlList.add(crlClient);
new C3_04_SignWithCRLOnline().sign(SRC, DEST + RESULT_FILES[0], chain, pk, DigestAlgorithms.SHA256,
provider.getName(), PdfSigner.CryptoStandard.CMS, "Test", "Ghent",
crlList, null, null, 0);
}
public void sign(String src, String dest, Certificate[] chain, PrivateKey pk,
String digestAlgorithm, String provider, PdfSigner.CryptoStandard subfilter,
String reason, String location, Collection<ICrlClient> crlList,
IOcspClient ocspClient, ITSAClient tsaClient, int estimatedSize)
throws GeneralSecurityException, IOException {
PdfReader reader = new PdfReader(src);
PdfSigner signer = new PdfSigner(reader, new FileOutputStream(dest), new StampingProperties());
// Create the signature appearance
Rectangle rect = new Rectangle(36, 648, 200, 100);
PdfSignatureAppearance appearance = signer.getSignatureAppearance();
appearance
.setReason(reason)
.setLocation(location)
.setPageRect(rect)
.setPageNumber(1);
signer.setFieldName("sig");
// Creating the signature
IExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm, provider);
IExternalDigest digest = new BouncyCastleDigest();
// Sign the document using the detached mode, CMS or CAdES equivalent.
// Pass the created CRL to the signing method.
signer.signDetached(digest, pks, chain, crlList, ocspClient, tsaClient, estimatedSize, subfilter);
}
}
C#
using System;
using System.Collections.Generic;
using System.IO;
using iText.Bouncycastle.Cert;
using iText.Bouncycastle.X509;
using iText.Bouncycastle.Crypto;
using iText.Commons.Bouncycastle.Cert;
using iText.Commons.Utils;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.X509;
using iText.Kernel.Geom;
using iText.Kernel.Pdf;
using iText.Signatures;
using Org.BouncyCastle.Pkcs;
namespace iText.Samples.Signatures.Chapter03
{
public class C3_04_SignWithCRLOnline
{
public static readonly string DEST = "results/signatures/chapter03/";
public static readonly string SRC = "../../../resources/pdfs/hello.pdf";
public static readonly String[] RESULT_FILES =
{
"hello_cacert_crl.pdf"
};
public static void Main(String[] args)
{
DirectoryInfo directory = new DirectoryInfo(DEST);
directory.Create();
Properties properties = new Properties();
// Specify the correct path to the certificate
properties.Load(new FileStream("c:/home/blowagie/key.properties", FileMode.Open, FileAccess.Read));
String path = properties.GetProperty("PRIVATE");
char[] pass = properties.GetProperty("PASSWORD").ToCharArray();
Pkcs12Store pk12 = new Pkcs12StoreBuilder().Build();
pk12.Load(new FileStream(path, FileMode.Open, FileAccess.Read), pass);
string alias = null;
foreach (var a in pk12.Aliases)
{
alias = ((string) a);
if (pk12.IsKeyEntry(alias))
break;
}
ICipherParameters pk = pk12.GetKey(alias).Key;
X509CertificateEntry[] ce = pk12.GetCertificateChain(alias);
X509Certificate[] chain = new X509Certificate[ce.Length];
for (int k = 0; k < ce.Length; ++k)
{
chain[k] = ce[k].Certificate;
}
/* Create a CrlClientOnline instance with specified Certificate Revocation List's URL.
* The exact URL for the CRL access point is specific for every CA provider.
* This one is specific for CAcert certificates.
*/
ICrlClient crlClient = new CrlClientOnline("https://crl.cacert.org/revoke.crl");
IList<ICrlClient> crlList = new List<ICrlClient>();
crlList.Add(crlClient);
new C3_04_SignWithCRLOnline().Sign(SRC, DEST + RESULT_FILES[0], chain, pk,
DigestAlgorithms.SHA256, PdfSigner.CryptoStandard.CMS,
"Test", "Ghent", crlList, null, null, 0);
}
public void Sign(String src, String dest, X509Certificate[] chain, ICipherParameters pk,
String digestAlgorithm, PdfSigner.CryptoStandard subfilter, String reason, String location,
ICollection<ICrlClient> crlList, IOcspClient ocspClient, ITSAClient tsaClient, int estimatedSize)
{
PdfReader reader = new PdfReader(src);
PdfSigner signer = new PdfSigner(reader, new FileStream(dest, FileMode.Create), new StampingProperties());
// Create the signature appearance
Rectangle rect = new Rectangle(36, 648, 200, 100);
PdfSignatureAppearance appearance = signer.GetSignatureAppearance();
appearance
.SetReason(reason)
.SetLocation(location)
// Specify if the appearance before field is signed will be used
// as a background for the signed field. The "false" value is the default value.
.SetReuseAppearance(false)
.SetPageRect(rect)
.SetPageNumber(1);
signer.SetFieldName("sig");
IExternalSignature pks = new PrivateKeySignature(new PrivateKeyBC(pk), digestAlgorithm);
IX509Certificate[] certificateWrappers = new IX509Certificate[chain.Length];
for (int i = 0; i < certificateWrappers.Length; ++i) {
certificateWrappers[i] = new X509CertificateBC(chain[i]);
}
// Sign the document using the detached mode, CMS or CAdES equivalent.
// Pass the created CRL to the signing method.
signer.SignDetached(pks, certificateWrappers, crlList, ocspClient, tsaClient, estimatedSize, subfilter);
}
}
}
c3_05_signwithcrloffline
Creating a CrlClient using an offline copy of the CRL:
java
package com.itextpdf.samples.signatures.chapter03;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.StampingProperties;
import com.itextpdf.signatures.BouncyCastleDigest;
import com.itextpdf.signatures.DigestAlgorithms;
import com.itextpdf.signatures.ICrlClient;
import com.itextpdf.signatures.CrlClientOffline;
import com.itextpdf.signatures.IExternalDigest;
import com.itextpdf.signatures.IExternalSignature;
import com.itextpdf.signatures.IOcspClient;
import com.itextpdf.signatures.ITSAClient;
import com.itextpdf.signatures.PdfSignatureAppearance;
import com.itextpdf.signatures.PdfSigner;
import com.itextpdf.signatures.PrivateKeySignature;
import java.io.ByteArrayOutputStream;
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 java.security.cert.CertificateFactory;
import java.security.cert.X509CRL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Properties;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
public class C3_05_SignWithCRLOffline {
public static final String DEST = "./target/test/resources/signatures/chapter03/";
public static final String CRLURL = "./src/test/resources/encryption/revoke.crl";
public static final String SRC = "./src/test/resources/pdfs/hello.pdf";
public static final String[] RESULT_FILES = new String[] {
"hello_cacert_crl_offline.pdf"
};
public static void main(String[] args) throws IOException, GeneralSecurityException {
File file = new File(DEST);
file.mkdirs();
Properties properties = new Properties();
// Specify the correct path to the certificate
properties.load(new FileInputStream("c:/home/blowagie/key.properties"));
String path = properties.getProperty("PRIVATE");
char[] pass = properties.getProperty("PASSWORD").toCharArray();
BouncyCastleProvider provider = new BouncyCastleProvider();
Security.addProvider(provider);
KeyStore ks = KeyStore.getInstance("pkcs12", provider.getName());
ks.load(new FileInputStream(path), pass);
String alias = ks.aliases().nextElement();
PrivateKey pk = (PrivateKey) ks.getKey(alias, pass);
Certificate[] chain = ks.getCertificateChain(alias);
FileInputStream is = new FileInputStream(CRLURL);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
while (is.read(buf) != -1) {
baos.write(buf);
}
/* Create a CrlClientOffline instance with the read CRL file's data.
* Given CRL file is specific to the CAcert provider and was downloaded long time ago.
* Make sure that you have the CRL specific for your certificate and CRL is up to date
* (by checking NextUpdate properties as seen below).
*/
ICrlClient crlClient = new CrlClientOffline(baos.toByteArray());
List<ICrlClient> crlList = new ArrayList<ICrlClient>();
crlList.add(crlClient);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509CRL crl = (X509CRL) cf.generateCRL(new FileInputStream(CRLURL));
System.out.println("CRL valid until: " + crl.getNextUpdate());
System.out.println("Certificate revoked: " + crl.isRevoked(chain[0]));
new C3_05_SignWithCRLOffline().sign(SRC, DEST + RESULT_FILES[0], chain, pk, DigestAlgorithms.SHA256,
provider.getName(), PdfSigner.CryptoStandard.CMS, "Test", "Ghent",
crlList, null, null, 0);
}
public void sign(String src, String dest, Certificate[] chain, PrivateKey pk,
String digestAlgorithm, String provider, PdfSigner.CryptoStandard subfilter,
String reason, String location, Collection<ICrlClient> crlList,
IOcspClient ocspClient, ITSAClient tsaClient, int estimatedSize)
throws GeneralSecurityException, IOException {
PdfReader reader = new PdfReader(src);
PdfSigner signer = new PdfSigner(reader, new FileOutputStream(dest), new StampingProperties());
// Create the signature appearance
Rectangle rect = new Rectangle(36, 648, 200, 100);
PdfSignatureAppearance appearance = signer.getSignatureAppearance();
appearance
.setReason(reason)
.setLocation(location)
.setPageRect(rect)
.setPageNumber(1);
signer.setFieldName("sig");
// Creating the signature
IExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm, provider);
IExternalDigest digest = new BouncyCastleDigest();
// Sign the document using the detached mode, CMS or CAdES equivalent.
// Pass the created CRL to the signing method.
signer.signDetached(digest, pks, chain, crlList, ocspClient, tsaClient, estimatedSize, subfilter);
}
}
C#
using System;
using System.Collections.Generic;
using System.IO;
using iText.Bouncycastle.Cert;
using iText.Bouncycastle.X509;
using iText.Bouncycastle.Crypto;
using iText.Commons.Bouncycastle.Cert;
using iText.Commons.Utils;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.X509;
using iText.Kernel.Geom;
using iText.Kernel.Pdf;
using iText.Signatures;
using Org.BouncyCastle.Pkcs;
namespace iText.Samples.Signatures.Chapter03
{
public class C3_05_SignWithCRLOffline
{
public static readonly string DEST = "results/signatures/chapter03/";
public static readonly string CRLURL = "../../../resources/encryption/revoke.crl";
public static readonly string SRC = "../../../resources/pdfs/hello.pdf";
public static readonly String[] RESULT_FILES =
{
"hello_cacert_crl_offline.pdf"
};
public static void Main(String[] args)
{
DirectoryInfo directory = new DirectoryInfo(DEST);
directory.Create();
Properties properties = new Properties();
// Specify the correct path to the certificate
properties.Load(new FileStream("c:/home/blowagie/key.properties", FileMode.Open, FileAccess.Read));
String path = properties.GetProperty("PRIVATE");
char[] pass = properties.GetProperty("PASSWORD").ToCharArray();
Pkcs12Store pk12 = new Pkcs12StoreBuilder().Build();
pk12.Load(new FileStream(path, FileMode.Open, FileAccess.Read), pass);
string alias = null;
foreach (var a in pk12.Aliases)
{
alias = ((string) a);
if (pk12.IsKeyEntry(alias))
break;
}
ICipherParameters pk = pk12.GetKey(alias).Key;
X509CertificateEntry[] ce = pk12.GetCertificateChain(alias);
X509Certificate[] chain = new X509Certificate[ce.Length];
for (int k = 0; k < ce.Length; ++k)
{
chain[k] = ce[k].Certificate;
}
FileStream fileStream = new FileStream(CRLURL, FileMode.Open, FileAccess.Read);
MemoryStream baos = new MemoryStream();
byte[] buf = new byte[1024];
while (fileStream.Read(buf, 0, buf.Length) != 0)
{
baos.Write(buf, 0, buf.Length);
}
/* Create a CrlClientOffline instance with the read CRL file's data.
* Given CRL file is specific to the CAcert provider and was downloaded long time ago.
* Make sure that you have the CRL specific for your certificate and CRL is up to date
* (by checking NextUpdate properties as seen below).
*/
ICrlClient crlClient = new CrlClientOffline(baos.ToArray());
X509Crl crl = new X509CrlParser().ReadCrl(new FileStream(CRLURL, FileMode.Open, FileAccess.Read));
Console.WriteLine("CRL valid until: " + crl.NextUpdate);
Console.WriteLine("Certificate revoked: " + crl.IsRevoked(chain[0]));
IList<ICrlClient> crlList = new List<ICrlClient>();
crlList.Add(crlClient);
new C3_05_SignWithCRLOffline().Sign(SRC, DEST + RESULT_FILES[0], chain, pk,
DigestAlgorithms.SHA256, PdfSigner.CryptoStandard.CMS, "Test", "Ghent",
crlList, null, null, 0);
}
public void Sign(String src, String dest, X509Certificate[] chain, ICipherParameters pk,
String digestAlgorithm, PdfSigner.CryptoStandard subfilter, String reason, String location,
ICollection<ICrlClient> crlList, IOcspClient ocspClient, ITSAClient tsaClient, int estimatedSize)
{
PdfReader reader = new PdfReader(src);
PdfSigner signer = new PdfSigner(reader, new FileStream(dest, FileMode.Create), new StampingProperties());
// Create the signature appearance
Rectangle rect = new Rectangle(36, 648, 200, 100);
PdfSignatureAppearance appearance = signer.GetSignatureAppearance();
appearance
.SetReason(reason)
.SetLocation(location)
// Specify if the appearance before field is signed will be used
// as a background for the signed field. The "false" value is the default value.
.SetReuseAppearance(false)
.SetPageRect(rect)
.SetPageNumber(1);
signer.SetFieldName("sig");
IExternalSignature pks = new PrivateKeySignature(new PrivateKeyBC(pk), digestAlgorithm);
IX509Certificate[] certificateWrappers = new IX509Certificate[chain.Length];
for (int i = 0; i < certificateWrappers.Length; ++i) {
certificateWrappers[i] = new X509CertificateBC(chain[i]);
}
// Sign the document using the detached mode, CMS or CAdES equivalent.
// Pass the created CRL to the signing method.
signer.SignDetached(pks, certificateWrappers, crlList, ocspClient, tsaClient, estimatedSize, subfilter);
}
}
}
c3_06_getocspurl
Fetching the Online Certificate Status Protocol (OCSP) URL from a certificate:
java
package com.itextpdf.samples.signatures.chapter03;
import com.itextpdf.signatures.CertificateUtil;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.Security;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.Properties;
public class C3_06_GetOcspUrl {
public static void main(String[] args) throws IOException, GeneralSecurityException {
Properties properties = new Properties();
// Specify the correct path to the certificate
properties.load(new FileInputStream("c:/home/blowagie/key.properties"));
String path = properties.getProperty("PRIVATE");
char[] pass = properties.getProperty("PASSWORD").toCharArray();
BouncyCastleProvider provider = new BouncyCastleProvider();
Security.addProvider(provider);
KeyStore ks = KeyStore.getInstance("pkcs12", provider.getName());
ks.load(new FileInputStream(path), pass);
String alias = ks.aliases().nextElement();
Certificate[] chain = ks.getCertificateChain(alias);
for (int i = 0; i < chain.length; i++) {
X509Certificate cert = (X509Certificate) chain[i];
System.out.println(String.format("[%s] %s", i, cert.getSubjectDN()));
System.out.println(CertificateUtil.getOCSPURL(cert));
}
}
}
C#
using System;
using System.IO;
using iText.Bouncycastle.Cert;
using iText.Bouncycastle.X509;
using iText.Commons.Utils;
using Org.BouncyCastle.X509;
using iText.Signatures;
using Org.BouncyCastle.Pkcs;
namespace iText.Samples.Signatures.Chapter03
{
public class C3_06_GetOcspUrl
{
public static void Main(String[] args)
{
Properties properties = new Properties();
// Specify the correct path to the certificate
properties.Load(new FileStream("c:/home/blowagie/key.properties", FileMode.Open, FileAccess.Read));
String path = properties.GetProperty("PRIVATE");
char[] pass = properties.GetProperty("PASSWORD").ToCharArray();
Pkcs12Store pk12 = new Pkcs12StoreBuilder().Build();
pk12.Load(new FileStream(path, FileMode.Open, FileAccess.Read), pass);
string alias = null;
foreach (var a in pk12.Aliases)
{
alias = ((string) a);
if (pk12.IsKeyEntry(alias))
break;
}
X509CertificateEntry[] ce = pk12.GetCertificateChain(alias);
X509Certificate[] chain = new X509Certificate[ce.Length];
for (int k = 0; k < ce.Length; ++k)
{
chain[k] = ce[k].Certificate;
}
for (int i = 0; i < chain.Length; i++)
{
X509Certificate cert = chain[i];
Console.WriteLine("[{0}] {1}", i, cert.SubjectDN);
Console.WriteLine(CertificateUtil.GetOCSPURL(new X509CertificateBC(cert)));
}
}
}
}
c3_07_signwithocsp
Signing a document with the OCSP:
java
package com.itextpdf.samples.signatures.chapter03;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.StampingProperties;
import com.itextpdf.signatures.BouncyCastleDigest;
import com.itextpdf.signatures.DigestAlgorithms;
import com.itextpdf.signatures.ICrlClient;
import com.itextpdf.signatures.IExternalDigest;
import com.itextpdf.signatures.IExternalSignature;
import com.itextpdf.signatures.IOcspClient;
import com.itextpdf.signatures.ITSAClient;
import com.itextpdf.signatures.OcspClientBouncyCastle;
import com.itextpdf.signatures.PdfSignatureAppearance;
import com.itextpdf.signatures.PdfSigner;
import com.itextpdf.signatures.PrivateKeySignature;
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 java.util.Collection;
import java.util.Properties;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
public class C3_07_SignWithOCSP {
public static final String DEST = "./target/test/resources/signatures/chapter03/";
public static final String SRC = "./src/test/resources/pdfs/hello.pdf";
public static final String[] RESULT_FILES = new String[] {
"hello_cacert_ocsp.pdf"
};
public static void main(String[] args) throws IOException, GeneralSecurityException {
File file = new File(DEST);
file.mkdirs();
Properties properties = new Properties();
// Specify the correct path to the certificate
properties.load(new FileInputStream("c:/home/blowagie/key.properties"));
String path = properties.getProperty("PRIVATE");
char[] pass = properties.getProperty("PASSWORD").toCharArray();
BouncyCastleProvider provider = new BouncyCastleProvider();
Security.addProvider(provider);
KeyStore ks = KeyStore.getInstance("pkcs12", provider.getName());
ks.load(new FileInputStream(path), pass);
String alias = ks.aliases().nextElement();
PrivateKey pk = (PrivateKey) ks.getKey(alias, pass);
Certificate[] chain = ks.getCertificateChain(alias);
/* Create an instance of OcspClientBouncyCastle, an implementation of OcspClient.
* In the current sample it is not needed to verify the OCSP response,
* that is why null is passed as verifier parameter.
*/
IOcspClient ocspClient = new OcspClientBouncyCastle(null);
new C3_07_SignWithOCSP().sign(SRC, DEST + RESULT_FILES[0], chain, pk,
DigestAlgorithms.SHA256, provider.getName(),
PdfSigner.CryptoStandard.CMS, "Test", "Ghent",
null, ocspClient, null, 0);
}
public void sign(String src, String dest, Certificate[] chain, PrivateKey pk,
String digestAlgorithm, String provider, PdfSigner.CryptoStandard subfilter,
String reason, String location, Collection<ICrlClient> crlList,
IOcspClient ocspClient, ITSAClient tsaClient, int estimatedSize)
throws GeneralSecurityException, IOException {
PdfReader reader = new PdfReader(src);
PdfSigner signer = new PdfSigner(reader, new FileOutputStream(dest), new StampingProperties());
// Create the signature appearance
Rectangle rect = new Rectangle(36, 648, 200, 100);
PdfSignatureAppearance appearance = signer.getSignatureAppearance();
appearance
.setReason(reason)
.setLocation(location)
// Specify if the appearance before field is signed will be used
// as a background for the signed field. The "false" value is the default value.
.setReuseAppearance(false)
.setPageRect(rect)
.setPageNumber(1);
signer.setFieldName("sig");
// Creating the signature
IExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm, provider);
IExternalDigest digest = new BouncyCastleDigest();
// Sign the document using the detached mode, CMS or CAdES equivalent.
// Pass the created OcspClient to the signing method.
signer.signDetached(digest, pks, chain, crlList, ocspClient, tsaClient, estimatedSize, subfilter);
}
}
C#
using System;
using System.Collections.Generic;
using System.IO;
using iText.Bouncycastle.Cert;
using iText.Bouncycastle.X509;
using iText.Bouncycastle.Crypto;
using iText.Commons.Bouncycastle.Cert;
using iText.Commons.Utils;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.X509;
using iText.Kernel.Geom;
using iText.Kernel.Pdf;
using iText.Signatures;
using Org.BouncyCastle.Pkcs;
namespace iText.Samples.Signatures.Chapter03
{
public class C3_07_SignWithOCSP
{
public static readonly string DEST = "results/signatures/chapter03/";
public static readonly string SRC = "../../../resources/pdfs/hello.pdf";
public static readonly String[] RESULT_FILES =
{
"hello_cacert_ocsp.pdf"
};
public static void Main(String[] args)
{
DirectoryInfo directory = new DirectoryInfo(DEST);
directory.Create();
Properties properties = new Properties();
// Specify the correct path to the certificate
properties.Load(new FileStream("c:/home/blowagie/key.properties", FileMode.Open, FileAccess.Read));
String path = properties.GetProperty("PRIVATE");
char[] pass = properties.GetProperty("PASSWORD").ToCharArray();
Pkcs12Store pk12 = new Pkcs12StoreBuilder().Build();
pk12.Load(new FileStream(path, FileMode.Open, FileAccess.Read), pass);
string alias = null;
foreach (var a in pk12.Aliases)
{
alias = ((string) a);
if (pk12.IsKeyEntry(alias))
break;
}
ICipherParameters pk = pk12.GetKey(alias).Key;
X509CertificateEntry[] ce = pk12.GetCertificateChain(alias);
X509Certificate[] chain = new X509Certificate[ce.Length];
for (int k = 0; k < ce.Length; ++k)
{
chain[k] = ce[k].Certificate;
}
/* Create an instance of OcspClientBouncyCastle, an implementation of OcspClient.
* In the current sample it is not needed to verify the OCSP response,
* that is why null is passed as verifier parameter.
*/
IOcspClient ocspClient = new OcspClientBouncyCastle(null);
new C3_07_SignWithOCSP().Sign(SRC, DEST + RESULT_FILES[0], chain, pk,
DigestAlgorithms.SHA256, PdfSigner.CryptoStandard.CMS,
"Test", "Ghent", null, ocspClient, null, 0);
}
public void Sign(String src, String dest, X509Certificate[] chain, ICipherParameters pk,
String digestAlgorithm, PdfSigner.CryptoStandard subfilter, String reason, String location,
ICollection<ICrlClient> crlList, IOcspClient ocspClient, ITSAClient tsaClient, int estimatedSize)
{
PdfReader reader = new PdfReader(src);
PdfSigner signer = new PdfSigner(reader, new FileStream(dest, FileMode.Create), new StampingProperties());
// Create the signature appearance
Rectangle rect = new Rectangle(36, 648, 200, 100);
PdfSignatureAppearance appearance = signer.GetSignatureAppearance();
appearance
.SetReason(reason)
.SetLocation(location)
// Specify if the appearance before field is signed will be used
// as a background for the signed field. The "false" value is the default value.
.SetReuseAppearance(false)
.SetPageRect(rect)
.SetPageNumber(1);
signer.SetFieldName("sig");
IExternalSignature pks = new PrivateKeySignature(new PrivateKeyBC(pk), digestAlgorithm);
IX509Certificate[] certificateWrappers = new IX509Certificate[chain.Length];
for (int i = 0; i < certificateWrappers.Length; ++i) {
certificateWrappers[i] = new X509CertificateBC(chain[i]);
}
// Sign the document using the detached mode, CMS or CAdES equivalent.
// Pass the created OcspClient to the signing method.
signer.SignDetached(pks, certificateWrappers, crlList, ocspClient, tsaClient, estimatedSize, subfilter);
}
}
}
c3_08_gettsaurl
Extracting a Time Stamping Authority (TSA) URL from a certificate:
java
package com.itextpdf.samples.signatures.chapter03;
import com.itextpdf.signatures.CertificateUtil;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.Security;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.Properties;
public class C3_08_GetTsaUrl {
public static void main(String[] args) throws IOException, GeneralSecurityException {
Properties properties = new Properties();
// Specify the correct path to the certificate
properties.load(new FileInputStream("c:/home/blowagie/key.properties"));
String path = properties.getProperty("PRIVATE");
char[] pass = properties.getProperty("PASSWORD").toCharArray();
BouncyCastleProvider provider = new BouncyCastleProvider();
Security.addProvider(provider);
KeyStore ks = KeyStore.getInstance("pkcs12", provider.getName());
ks.load(new FileInputStream(path), pass);
String alias = ks.aliases().nextElement();
Certificate[] chain = ks.getCertificateChain(alias);
for (int i = 0; i < chain.length; i++) {
X509Certificate cert = (X509Certificate) chain[i];
System.out.println(String.format("[%s] %s", i, cert.getSubjectDN()));
System.out.println(CertificateUtil.getTSAURL(cert));
}
}
}
C#
using System;
using System.IO;
using iText.Bouncycastle.Cert;
using iText.Bouncycastle.X509;
using iText.Commons.Utils;
using Org.BouncyCastle.X509;
using iText.Signatures;
using Org.BouncyCastle.Pkcs;
namespace iText.Samples.Signatures.Chapter03
{
public class C3_08_GetTsaUrl
{
public static void Main(String[] args)
{
Properties properties = new Properties();
// Specify the correct path to the certificate
properties.Load(new FileStream("c:/home/blowagie/key.properties", FileMode.Open, FileAccess.Read));
String path = properties.GetProperty("PRIVATE");
char[] pass = properties.GetProperty("PASSWORD").ToCharArray();
Pkcs12Store pk12 = new Pkcs12StoreBuilder().Build();
pk12.Load(new FileStream(path, FileMode.Open, FileAccess.Read), pass);
string alias = null;
foreach (var a in pk12.Aliases)
{
alias = ((string) a);
if (pk12.IsKeyEntry(alias))
break;
}
X509CertificateEntry[] ce = pk12.GetCertificateChain(alias);
X509Certificate[] chain = new X509Certificate[ce.Length];
for (int k = 0; k < ce.Length; ++k)
{
chain[k] = ce[k].Certificate;
}
for (int i = 0; i < chain.Length; i++)
{
X509Certificate cert = chain[i];
Console.WriteLine("[{0}] {1}", i, cert.SubjectDN);
Console.WriteLine(CertificateUtil.GetTSAURL(new X509CertificateBC(cert)));
}
}
}
}
c3_09_signwithtsa
Signing a document with TSAClientBouncyCastle, an implementation of TSAClient:
java
package com.itextpdf.samples.signatures.chapter03;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.StampingProperties;
import com.itextpdf.signatures.BouncyCastleDigest;
import com.itextpdf.signatures.DigestAlgorithms;
import com.itextpdf.signatures.ICrlClient;
import com.itextpdf.signatures.IExternalDigest;
import com.itextpdf.signatures.IExternalSignature;
import com.itextpdf.signatures.IOcspClient;
import com.itextpdf.signatures.OcspClientBouncyCastle;
import com.itextpdf.signatures.PdfSignatureAppearance;
import com.itextpdf.signatures.PdfSigner;
import com.itextpdf.signatures.ITSAClient;
import com.itextpdf.signatures.PrivateKeySignature;
import com.itextpdf.signatures.TSAClientBouncyCastle;
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 java.util.Collection;
import java.util.Properties;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
public class C3_09_SignWithTSA {
public static final String DEST = "./target/test/resources/signatures/chapter03/";
public static final String SRC = "./src/test/resources/pdfs/hello.pdf";
public static final String[] RESULT_FILES = new String[] {
"hello_cacert_ocsp_ts.pdf"
};
public static void main(String[] args) throws IOException, GeneralSecurityException {
File file = new File(DEST);
file.mkdirs();
Properties properties = new Properties();
// Specify the correct path to the certificate
properties.load(new FileInputStream("c:/home/blowagie/key.properties"));
String path = properties.getProperty("PRIVATE");
char[] pass = properties.getProperty("PASSWORD").toCharArray();
String tsaUrl = properties.getProperty("TSAURL");
String tsaUser = properties.getProperty("TSAUSERNAME");
String tsaPass = properties.getProperty("TSAPASSWORD");
BouncyCastleProvider provider = new BouncyCastleProvider();
Security.addProvider(provider);
KeyStore ks = KeyStore.getInstance("pkcs12", provider.getName());
ks.load(new FileInputStream(path), pass);
String alias = ks.aliases().nextElement();
PrivateKey pk = (PrivateKey) ks.getKey(alias, pass);
Certificate[] chain = ks.getCertificateChain(alias);
IOcspClient ocspClient = new OcspClientBouncyCastle(null);
/* Create an instance of TSAClientBouncyCastle, an implementation of TSAClient.
* Pass the timestamp authority server url.
* Note that not all TSA would require user credentials.
*/
ITSAClient tsaClient = new TSAClientBouncyCastle(tsaUrl, tsaUser, tsaPass);
new C3_09_SignWithTSA().sign(SRC, DEST + RESULT_FILES[0], chain, pk,
DigestAlgorithms.SHA256, provider.getName(), PdfSigner.CryptoStandard.CMS,
"Test", "Ghent", null, ocspClient, tsaClient, 0);
}
public void sign(String src, String dest, Certificate[] chain, PrivateKey pk,
String digestAlgorithm, String provider, PdfSigner.CryptoStandard subfilter,
String reason, String location, Collection<ICrlClient> crlList,
IOcspClient ocspClient, ITSAClient tsaClient, int estimatedSize)
throws GeneralSecurityException, IOException {
PdfReader reader = new PdfReader(src);
PdfSigner signer = new PdfSigner(reader, new FileOutputStream(dest), new StampingProperties());
// Create the signature appearance
Rectangle rect = new Rectangle(36, 648, 200, 100);
PdfSignatureAppearance appearance = signer.getSignatureAppearance();
appearance
.setReason(reason)
.setLocation(location)
// Specify if the appearance before field is signed will be used
// as a background for the signed field. The "false" value is the default value.
.setReuseAppearance(false)
.setPageRect(rect)
.setPageNumber(1);
signer.setFieldName("sig");
// Creating the signature
IExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm, provider);
IExternalDigest digest = new BouncyCastleDigest();
// Sign the document using the detached mode, CMS or CAdES equivalent.
// Pass the created TSAClient to the signing method.
signer.signDetached(digest, pks, chain, crlList, ocspClient, tsaClient, estimatedSize, subfilter);
}
}
C#
using System;
using System.Collections.Generic;
using System.IO;
using iText.Bouncycastle.Cert;
using iText.Bouncycastle.X509;
using iText.Bouncycastle.Crypto;
using iText.Commons.Bouncycastle.Cert;
using iText.Commons.Utils;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.X509;
using iText.Kernel.Geom;
using iText.Kernel.Pdf;
using iText.Signatures;
using Org.BouncyCastle.Pkcs;
namespace iText.Samples.Signatures.Chapter03
{
public class C3_09_SignWithTSA
{
public static readonly string DEST = "results/signatures/chapter03/";
public static readonly string SRC = "../../../resources/pdfs/hello.pdf";
public static readonly String[] RESULT_FILES =
{
"hello_cacert_ocsp_ts.pdf"
};
public static void Main(String[] args)
{
DirectoryInfo directory = new DirectoryInfo(DEST);
directory.Create();
Properties properties = new Properties();
// Specify the correct path to the certificate
properties.Load(new FileStream("c:/home/blowagie/key.properties", FileMode.Open, FileAccess.Read));
String path = properties.GetProperty("PRIVATE");
char[] pass = properties.GetProperty("PASSWORD").ToCharArray();
String tsaUrl = properties.GetProperty("TSAURL");
String tsaUser = properties.GetProperty("TSAUSERNAME");
String tsaPass = properties.GetProperty("TSAPASSWORD");
Pkcs12Store pk12 = new Pkcs12StoreBuilder().Build();
pk12.Load(new FileStream(path, FileMode.Open, FileAccess.Read), pass);
string alias = null;
foreach (var a in pk12.Aliases)
{
alias = ((string)a);
if (pk12.IsKeyEntry(alias))
break;
}
ICipherParameters pk = pk12.GetKey(alias).Key;
X509CertificateEntry[] ce = pk12.GetCertificateChain(alias);
X509Certificate[] chain = new X509Certificate[ce.Length];
for (int k = 0; k < ce.Length; ++k)
{
chain[k] = ce[k].Certificate;
}
IOcspClient ocspClient = new OcspClientBouncyCastle(null);
/* Create an instance of TSAClientBouncyCastle, an implementation of TSAClient.
* Pass the timestamp authority server url.
* Note that not all TSA would require user credentials.
*/
ITSAClient tsaClient = new TSAClientBouncyCastle(tsaUrl, tsaUser, tsaPass);
new C3_09_SignWithTSA().Sign(SRC, DEST + RESULT_FILES[0], chain, pk,
DigestAlgorithms.SHA256, PdfSigner.CryptoStandard.CMS,
"Test", "Ghent", null, ocspClient, tsaClient, 0);
}
public void Sign(String src, String dest, X509Certificate[] chain, ICipherParameters pk,
String digestAlgorithm, PdfSigner.CryptoStandard subfilter, String reason, String location,
ICollection<ICrlClient> crlList, IOcspClient ocspClient, ITSAClient tsaClient, int estimatedSize)
{
PdfReader reader = new PdfReader(src);
PdfSigner signer = new PdfSigner(reader, new FileStream(dest, FileMode.Create), new StampingProperties());
// Create the signature appearance
Rectangle rect = new Rectangle(36, 648, 200, 100);
PdfSignatureAppearance appearance = signer.GetSignatureAppearance();
appearance
.SetReason(reason)
.SetLocation(location)
// Specify if the appearance before field is signed will be used
// as a background for the signed field. The "false" value is the default value.
.SetReuseAppearance(false)
.SetPageRect(rect)
.SetPageNumber(1);
signer.SetFieldName("sig");
IExternalSignature pks = new PrivateKeySignature(new PrivateKeyBC(pk), digestAlgorithm);
IX509Certificate[] certificateWrappers = new IX509Certificate[chain.Length];
for (int i = 0; i < certificateWrappers.Length; ++i) {
certificateWrappers[i] = new X509CertificateBC(chain[i]);
}
// Sign the document using the detached mode, CMS or CAdES equivalent.
// Pass the created TSAClient to the signing method.
signer.SignDetached(pks, certificateWrappers, crlList, ocspClient, tsaClient, estimatedSize, subfilter);
}
}
}
c3_10_signwithtsaevent
Adding an event to a TSAClientBouncyCastle instance:
java
package com.itextpdf.samples.signatures.chapter03;
import com.itextpdf.commons.bouncycastle.tsp.ITimeStampTokenInfo;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.StampingProperties;
import com.itextpdf.signatures.BouncyCastleDigest;
import com.itextpdf.signatures.DigestAlgorithms;
import com.itextpdf.signatures.ICrlClient;
import com.itextpdf.signatures.IExternalDigest;
import com.itextpdf.signatures.IExternalSignature;
import com.itextpdf.signatures.IOcspClient;
import com.itextpdf.signatures.ITSAClient;
import com.itextpdf.signatures.OcspClientBouncyCastle;
import com.itextpdf.signatures.PdfSignatureAppearance;
import com.itextpdf.signatures.PdfSigner;
import com.itextpdf.signatures.PrivateKeySignature;
import com.itextpdf.signatures.TSAClientBouncyCastle;
import com.itextpdf.signatures.ITSAInfoBouncyCastle;
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 java.util.Collection;
import java.util.Properties;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.tsp.TimeStampTokenInfo;
public class C3_10_SignWithTSAEvent {
public static final String DEST = "./target/test/resources/signatures/chapter03/";
public static final String SRC = "./src/test/resources/pdfs/hello.pdf";
public static final String[] RESULT_FILES = new String[] {
"hello_cacert_ocsp_ts.pdf"
};
public static void main(String[] args) throws IOException, GeneralSecurityException {
File file = new File(DEST);
file.mkdirs();
Properties properties = new Properties();
// Specify the correct path to the certificate
properties.load(new FileInputStream("c:/home/blowagie/key.properties"));
String path = properties.getProperty("PRIVATE");
char[] pass = properties.getProperty("PASSWORD").toCharArray();
String tsaUrl = properties.getProperty("TSAURL");
String tsaUser = properties.getProperty("TSAUSERNAME");
String tsaPass = properties.getProperty("TSAPASSWORD");
BouncyCastleProvider provider = new BouncyCastleProvider();
Security.addProvider(provider);
KeyStore ks = KeyStore.getInstance("pkcs12", provider.getName());
ks.load(new FileInputStream(path), pass);
String alias = ks.aliases().nextElement();
PrivateKey pk = (PrivateKey) ks.getKey(alias, pass);
Certificate[] chain = ks.getCertificateChain(alias);
IOcspClient ocspClient = new OcspClientBouncyCastle(null);
TSAClientBouncyCastle tsaClient = new TSAClientBouncyCastle(tsaUrl, tsaUser, tsaPass);
tsaClient.setTSAInfo(new ITSAInfoBouncyCastle() {
// TimeStampTokenInfo object contains much more information about the timestamp token,
// like serial number, TST hash algorithm, etc.
public void inspectTimeStampTokenInfo(ITimeStampTokenInfo info) {
System.out.println(info.getGenTime());
}
});
new C3_10_SignWithTSAEvent().sign(SRC, DEST + RESULT_FILES[0], chain, pk,
DigestAlgorithms.SHA256, provider.getName(), PdfSigner.CryptoStandard.CMS,
"Test", "Ghent", null, ocspClient, tsaClient, 0);
}
public void sign(String src, String dest, Certificate[] chain, PrivateKey pk,
String digestAlgorithm, String provider, PdfSigner.CryptoStandard subfilter,
String reason, String location, Collection<ICrlClient> crlList,
IOcspClient ocspClient, ITSAClient tsaClient, int estimatedSize)
throws GeneralSecurityException, IOException {
PdfReader reader = new PdfReader(src);
PdfSigner signer = new PdfSigner(reader, new FileOutputStream(dest), new StampingProperties());
// Create the signature appearance
Rectangle rect = new Rectangle(36, 648, 200, 100);
PdfSignatureAppearance appearance = signer.getSignatureAppearance();
appearance
.setReason(reason)
.setLocation(location)
// Specify if the appearance before field is signed will be used
// as a background for the signed field. The "false" value is the default value.
.setReuseAppearance(false)
.setPageRect(rect)
.setPageNumber(1);
signer.setFieldName("sig");
// Creating the signature
IExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm, provider);
IExternalDigest digest = new BouncyCastleDigest();
// Sign the document using the detached mode, CMS or CAdES equivalent.
signer.signDetached(digest, pks, chain, crlList, ocspClient, tsaClient, estimatedSize, subfilter);
}
}
C#
using System;
using System.Collections.Generic;
using System.IO;
using iText.Bouncycastle.Cert;
using iText.Bouncycastle.X509;
using iText.Bouncycastle.Crypto;
using iText.Commons.Bouncycastle.Cert;
using iText.Commons.Bouncycastle.Tsp;
using iText.Commons.Utils;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Tsp;
using Org.BouncyCastle.X509;
using iText.Kernel.Geom;
using iText.Kernel.Pdf;
using iText.Signatures;
using Org.BouncyCastle.Pkcs;
namespace iText.Samples.Signatures.Chapter03
{
public class C3_10_SignWithTSAEvent
{
public static readonly string DEST = "results/signatures/chapter03/";
public static readonly string SRC = "../../../resources/pdfs/hello.pdf";
public static readonly String[] RESULT_FILES =
{
"hello_cacert_ocsp_ts.pdf"
};
public static void Main(String[] args)
{
DirectoryInfo directory = new DirectoryInfo(DEST);
directory.Create();
Properties properties = new Properties();
// Specify the correct path to the certificate
properties.Load(new FileStream("c:/home/blowagie/key.properties", FileMode.Open, FileAccess.Read));
String path = properties.GetProperty("PRIVATE");
char[] pass = properties.GetProperty("PASSWORD").ToCharArray();
String tsaUrl = properties.GetProperty("TSAURL");
String tsaUser = properties.GetProperty("TSAUSERNAME");
String tsaPass = properties.GetProperty("TSAPASSWORD");
Pkcs12Store pk12 = new Pkcs12StoreBuilder().Build();
pk12.Load(new FileStream(path, FileMode.Open, FileAccess.Read), pass);
string alias = null;
foreach (var a in pk12.Aliases)
{
alias = ((string) a);
if (pk12.IsKeyEntry(alias))
break;
}
ICipherParameters pk = pk12.GetKey(alias).Key;
X509CertificateEntry[] ce = pk12.GetCertificateChain(alias);
X509Certificate[] chain = new X509Certificate[ce.Length];
for (int k = 0; k < ce.Length; ++k)
{
chain[k] = ce[k].Certificate;
}
IOcspClient ocspClient = new OcspClientBouncyCastle(null);
TSAClientBouncyCastle tsaClient = new TSAClientBouncyCastle(tsaUrl, tsaUser, tsaPass);
tsaClient.SetTSAInfo(new CustomITSAInfoBouncyCastle());
new C3_10_SignWithTSAEvent().Sign(SRC, DEST + RESULT_FILES[0], chain, pk,
DigestAlgorithms.SHA256, PdfSigner.CryptoStandard.CMS,
"Test", "Ghent", null, ocspClient, tsaClient, 0);
}
public void Sign(String src, String dest, X509Certificate[] chain, ICipherParameters pk,
String digestAlgorithm, PdfSigner.CryptoStandard subfilter, String reason, String location,
ICollection<ICrlClient> crlList, IOcspClient ocspClient, ITSAClient tsaClient, int estimatedSize)
{
PdfReader reader = new PdfReader(src);
PdfSigner signer = new PdfSigner(reader, new FileStream(dest, FileMode.Create), new StampingProperties());
// Create the signature appearance
Rectangle rect = new Rectangle(36, 648, 200, 100);
PdfSignatureAppearance appearance = signer.GetSignatureAppearance();
appearance
.SetReason(reason)
.SetLocation(location)
// Specify if the appearance before field is signed will be used
// as a background for the signed field. The "false" value is the default value.
.SetReuseAppearance(false)
.SetPageRect(rect)
.SetPageNumber(1);
signer.SetFieldName("sig");
IExternalSignature pks = new PrivateKeySignature(new PrivateKeyBC(pk), digestAlgorithm);
IX509Certificate[] certificateWrappers = new IX509Certificate[chain.Length];
for (int i = 0; i < certificateWrappers.Length; ++i) {
certificateWrappers[i] = new X509CertificateBC(chain[i]);
}
// Sign the document using the detached mode, CMS or CAdES equivalent.
// Pass the created TSAClient to the signing method.
signer.SignDetached(pks, certificateWrappers, crlList, ocspClient, tsaClient, estimatedSize, subfilter);
}
private class CustomITSAInfoBouncyCastle : ITSAInfoBouncyCastle
{
// TimeStampTokenInfo object contains much more information about the timestamp token,
// like serial number, TST hash algorithm, etc.
public void InspectTimeStampTokenInfo(ITimeStampTokenInfo info)
{
Console.WriteLine(info.GetGenTime());
}
}
}
}
c3_11_signwithtoken
Signing a document with a USB token using Microsoft CryptoAPI (MSCAPI) - currently only available for Java:
java
package com.itextpdf.samples.signatures.chapter03;
import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.StampingProperties;
import com.itextpdf.signatures.BouncyCastleDigest;
import com.itextpdf.signatures.CertificateUtil;
import com.itextpdf.signatures.CrlClientOnline;
import com.itextpdf.signatures.DigestAlgorithms;
import com.itextpdf.signatures.ICrlClient;
import com.itextpdf.signatures.IExternalDigest;
import com.itextpdf.signatures.IExternalSignature;
import com.itextpdf.signatures.IOcspClient;
import com.itextpdf.signatures.ITSAClient;
import com.itextpdf.signatures.OcspClientBouncyCastle;
import com.itextpdf.signatures.PdfSignatureAppearance;
import com.itextpdf.signatures.PdfSigner;
import com.itextpdf.signatures.PrivateKeySignature;
import com.itextpdf.signatures.TSAClientBouncyCastle;
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.security.cert.X509Certificate;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
public class C3_11_SignWithToken {
public static final String SRC = "./src/test/resources/pdfs/hello.pdf";
public static final String DEST = "./target/test/resources/signatures/chapter03/";
public static final String[] RESULT_FILES = new String[] {
"hello_token.pdf"
};
public static void main(String[] args) throws IOException, GeneralSecurityException {
File file = new File(DEST);
file.mkdirs();
BouncyCastleProvider providerBC = new BouncyCastleProvider();
Security.addProvider(providerBC);
/* This isn’t really necessary to explicitly add the instance of SunMSCAPI to the providers list,
* because if this provider is available in JDK, then it's expected that it is already registered.
* However, SunMSCAPI is a part of the sun.* packages, which are not part of the supported,
* public interface. If this part of code can be complied without errors, then your JDK
* still supports SunMSCAPI.
*/
// SunMSCAPI providerMSCAPI = new SunMSCAPI();
// Security.addProvider(providerMSCAPI);
KeyStore ks = KeyStore.getInstance("Windows-MY");
/* Because of creating a Keystore instance using the parameter “Windows-MY”,
* all the signing operations are passed to the Microsoft CryptoAPI.
* That is why the stream and password are null.
*/
ks.load(null, null);
String alias = "Bruno Lowagie";
PrivateKey pk = (PrivateKey) ks.getKey(alias, null);
Certificate[] chain = ks.getCertificateChain(alias);
IOcspClient ocspClient = new OcspClientBouncyCastle(null);
ITSAClient tsaClient = null;
for (int i = 0; i < chain.length; i++) {
X509Certificate cert = (X509Certificate) chain[i];
String tsaUrl = CertificateUtil.getTSAURL(cert);
if (tsaUrl != null) {
tsaClient = new TSAClientBouncyCastle(tsaUrl);
break;
}
}
List<ICrlClient> crlList = new ArrayList<ICrlClient>();
crlList.add(new CrlClientOnline(chain));
// This provider name can be used only if JDK supports it.
String mscapiName = "SunMSCAPI";
new C3_11_SignWithToken().sign(SRC, DEST + RESULT_FILES[0], chain, pk, DigestAlgorithms.SHA384,
mscapiName, PdfSigner.CryptoStandard.CMS, "Test", "Ghent",
crlList, ocspClient, tsaClient, 0);
}
public void sign(String src, String dest, Certificate[] chain, PrivateKey pk,
String digestAlgorithm, String provider, PdfSigner.CryptoStandard subfilter,
String reason, String location, Collection<ICrlClient> crlList,
IOcspClient ocspClient, ITSAClient tsaClient, int estimatedSize)
throws GeneralSecurityException, IOException {
PdfReader reader = new PdfReader(src);
PdfSigner signer = new PdfSigner(reader, new FileOutputStream(dest), new StampingProperties());
// Create the signature appearance
Rectangle rect = new Rectangle(36, 648, 200, 100);
PdfSignatureAppearance appearance = signer.getSignatureAppearance();
appearance
.setReason(reason)
.setLocation(location)
// Specify if the appearance before field is signed will be used
// as a background for the signed field. The "false" value is the default value.
.setReuseAppearance(false)
.setPageRect(rect)
.setPageNumber(1);
signer.setFieldName("sig");
// Creating the signature
IExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm, provider);
IExternalDigest digest = new BouncyCastleDigest();
// Sign the document using the detached mode, CMS or CAdES equivalent.
signer.signDetached(digest, pks, chain, crlList, ocspClient, tsaClient, estimatedSize, subfilter);
}
}
c3_12_signwithestimatedsize
Estimating the size in bytes of the signature content:
java
package com.itextpdf.samples.signatures.chapter03;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.StampingProperties;
import com.itextpdf.signatures.BouncyCastleDigest;
import com.itextpdf.signatures.DigestAlgorithms;
import com.itextpdf.signatures.ICrlClient;
import com.itextpdf.signatures.IExternalDigest;
import com.itextpdf.signatures.IExternalSignature;
import com.itextpdf.signatures.IOcspClient;
import com.itextpdf.signatures.OcspClientBouncyCastle;
import com.itextpdf.signatures.PdfSignatureAppearance;
import com.itextpdf.signatures.PdfSigner;
import com.itextpdf.signatures.ITSAClient;
import com.itextpdf.signatures.PrivateKeySignature;
import com.itextpdf.signatures.TSAClientBouncyCastle;
import java.io.FileOutputStream;
import java.util.Collection;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import java.io.File;
import java.io.FileInputStream;
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.Properties;
public class C3_12_SignWithEstimatedSize {
public static final String DEST = "./target/test/resources/signatures/chapter03/";
public static final String SRC = "./src/test/resources/pdfs/hello.pdf";
public static final String[] RESULT_FILES = new String[] {
"hello_estimated.pdf"
};
public static void main(String[] args) throws IOException, GeneralSecurityException {
File file = new File(DEST);
file.mkdirs();
Properties properties = new Properties();
// Specify the correct path to the certificate
properties.load(new FileInputStream("c:/home/blowagie/key.properties"));
String path = properties.getProperty("PRIVATE");
char[] pass = properties.getProperty("PASSWORD").toCharArray();
String tsaUrl = properties.getProperty("TSAURL");
String tsaUser = properties.getProperty("TSAUSERNAME");
String tsaPass = properties.getProperty("TSAPASSWORD");
BouncyCastleProvider provider = new BouncyCastleProvider();
Security.addProvider(provider);
KeyStore ks = KeyStore.getInstance("pkcs12", provider.getName());
ks.load(new FileInputStream(path), pass);
String alias = ks.aliases().nextElement();
PrivateKey pk = (PrivateKey) ks.getKey(alias, pass);
Certificate[] chain = ks.getCertificateChain(alias);
IOcspClient ocspClient = new OcspClientBouncyCastle(null);
ITSAClient tsaClient = new TSAClientBouncyCastle(tsaUrl, tsaUser, tsaPass);
C3_12_SignWithEstimatedSize app = new C3_12_SignWithEstimatedSize();
boolean succeeded = false;
int estimatedSize = 1000;
while (!succeeded) {
try {
System.out.println("Attempt: " + estimatedSize + " bytes");
app.sign(SRC, DEST + RESULT_FILES[0], chain, pk, DigestAlgorithms.SHA256,
provider.getName(), PdfSigner.CryptoStandard.CMS, "Test", "Ghent",
null, ocspClient, tsaClient, estimatedSize);
succeeded = true;
System.out.println("Succeeded!");
} catch (IOException ioe) {
System.out.println("Not succeeded: " + ioe.getMessage());
estimatedSize += 50;
}
}
}
public void sign(String src, String dest, Certificate[] chain, PrivateKey pk,
String digestAlgorithm, String provider, PdfSigner.CryptoStandard subfilter,
String reason, String location, Collection<ICrlClient> crlList,
IOcspClient ocspClient, ITSAClient tsaClient, int estimatedSize)
throws GeneralSecurityException, IOException {
PdfReader reader = new PdfReader(src);
PdfSigner signer = new PdfSigner(reader, new FileOutputStream(dest), new StampingProperties());
// Create the signature appearance
Rectangle rect = new Rectangle(36, 648, 200, 100);
PdfSignatureAppearance appearance = signer.getSignatureAppearance();
appearance
.setReason(reason)
.setLocation(location)
// Specify if the appearance before field is signed will be used
// as a background for the signed field. The "false" value is the default value.
.setReuseAppearance(false)
.setPageRect(rect)
.setPageNumber(1);
signer.setFieldName("sig");
// Creating the signature
IExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm, provider);
IExternalDigest digest = new BouncyCastleDigest();
// Sign the document using the detached mode, CMS or CAdES equivalent.
signer.signDetached(digest, pks, chain, crlList, ocspClient, tsaClient, estimatedSize, subfilter);
}
}
C#
using System;
using System.Collections.Generic;
using System.IO;
using iText.Bouncycastle.Cert;
using iText.Bouncycastle.X509;
using iText.Bouncycastle.Crypto;
using iText.Commons.Bouncycastle.Cert;
using iText.Commons.Utils;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.X509;
using iText.Kernel.Geom;
using iText.Kernel.Pdf;
using iText.Signatures;
using Org.BouncyCastle.Pkcs;
namespace iText.Samples.Signatures.Chapter03
{
public class C3_12_SignWithEstimatedSize
{
public static readonly string DEST = "results/signatures/chapter03/";
public static readonly string SRC = "../../../resources/pdfs/hello.pdf";
public static readonly String[] RESULT_FILES =
{
"hello_estimated.pdf"
};
public static void Main(String[] args)
{
DirectoryInfo directory = new DirectoryInfo(DEST);
directory.Create();
Properties properties = new Properties();
// Specify the correct path to the certificate
properties.Load(new FileStream("c:/home/blowagie/key.properties", FileMode.Open, FileAccess.Read));
String path = properties.GetProperty("PRIVATE");
char[] pass = properties.GetProperty("PASSWORD").ToCharArray();
String tsaUrl = properties.GetProperty("TSAURL");
String tsaUser = properties.GetProperty("TSAUSERNAME");
String tsaPass = properties.GetProperty("TSAPASSWORD");
Pkcs12Store pk12 = new Pkcs12StoreBuilder().Build();
pk12.Load(new FileStream(path, FileMode.Open, FileAccess.Read), pass);
string alias = null;
foreach (var a in pk12.Aliases)
{
alias = ((string) a);
if (pk12.IsKeyEntry(alias))
break;
}
ICipherParameters pk = pk12.GetKey(alias).Key;
X509CertificateEntry[] ce = pk12.GetCertificateChain(alias);
X509Certificate[] chain = new X509Certificate[ce.Length];
for (int k = 0; k < ce.Length; ++k)
{
chain[k] = ce[k].Certificate;
}
IOcspClient ocspClient = new OcspClientBouncyCastle(null);
ITSAClient tsaClient = new TSAClientBouncyCastle(tsaUrl, tsaUser, tsaPass);
C3_12_SignWithEstimatedSize app = new C3_12_SignWithEstimatedSize();
bool succeeded = false;
int estimatedSize = 1000;
while (!succeeded)
{
try
{
Console.WriteLine("Attempt: " + estimatedSize + " bytes");
app.Sign(SRC, DEST, chain, pk, DigestAlgorithms.SHA256, PdfSigner.CryptoStandard.CMS,
"Test", "Ghent", null, ocspClient, tsaClient, estimatedSize);
succeeded = true;
Console.WriteLine("Succeeded!");
}
catch (IOException ioe)
{
Console.WriteLine("Not succeeded: " + ioe.Message);
estimatedSize += 50;
}
}
}
public void Sign(String src, String dest, X509Certificate[] chain, ICipherParameters pk,
String digestAlgorithm, PdfSigner.CryptoStandard subfilter, String reason, String location,
ICollection<ICrlClient> crlList, IOcspClient ocspClient, ITSAClient tsaClient, int estimatedSize)
{
PdfReader reader = new PdfReader(src);
PdfSigner signer = new PdfSigner(reader, new FileStream(dest, FileMode.Create), new StampingProperties());
// Create the signature appearance
Rectangle rect = new Rectangle(36, 648, 200, 100);
PdfSignatureAppearance appearance = signer.GetSignatureAppearance();
appearance
.SetReason(reason)
.SetLocation(location)
// Specify if the appearance before field is signed will be used
// as a background for the signed field. The "false" value is the default value.
.SetReuseAppearance(false)
.SetPageRect(rect)
.SetPageNumber(1);
signer.SetFieldName("sig");
IExternalSignature pks = new PrivateKeySignature(new PrivateKeyBC(pk), digestAlgorithm);
IX509Certificate[] certificateWrappers = new IX509Certificate[chain.Length];
for (int i = 0; i < certificateWrappers.Length; ++i) {
certificateWrappers[i] = new X509CertificateBC(chain[i]);
}
// Sign the document using the detached mode, CMS or CAdES equivalent.
signer.SignDetached(pks, certificateWrappers, crlList, ocspClient, tsaClient, estimatedSize, subfilter);
}
}
}