Digital signatures - chapter 4

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

1st November 2015
admin-marketing

Switch code for this example

C4_01_SignWithPKCS11HSM.java
package signatures.chapter4;

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.Provider;
import java.security.Security;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Properties;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

import sun.security.pkcs11.SunPKCS11;

import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.log.LoggerFactory;
import com.itextpdf.text.log.SysoLogger;
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.CertificateUtil;
import com.itextpdf.text.pdf.security.CrlClient;
import com.itextpdf.text.pdf.security.CrlClientOnline;
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.OcspClient;
import com.itextpdf.text.pdf.security.OcspClientBouncyCastle;
import com.itextpdf.text.pdf.security.PrivateKeySignature;
import com.itextpdf.text.pdf.security.TSAClient;
import com.itextpdf.text.pdf.security.TSAClientBouncyCastle;
import com.itextpdf.text.pdf.security.MakeSignature.CryptoStandard;

public class C4_01_SignWithPKCS11HSM {
	
	public static final String SRC = "/home/itext/hello.pdf";
	public static final String PROPS = "/home/itext/key.properties";
	public static final String DEST = "/home/itext/hello_hsm.pdf";

	public void sign(String src, String dest,
			Certificate[] chain, PrivateKey pk,
			String digestAlgorithm, String provider, CryptoStandard subfilter,
			String reason, String location,
			Collection crlList,
			OcspClient ocspClient,
			TSAClient tsaClient,
			int estimatedSize)
					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
        ExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm, provider);
        ExternalDigest digest = new BouncyCastleDigest();
        MakeSignature.signDetached(appearance, digest, pks, chain, crlList, ocspClient, tsaClient, estimatedSize, subfilter);
	}
	
	public static void main(String[] args) throws IOException, GeneralSecurityException, DocumentException {

		LoggerFactory.getInstance().setLogger(new SysoLogger());
		
		Properties properties = new Properties();
		properties.load(new FileInputStream(PROPS));
        char[] pass = properties.getProperty("PASSWORD").toCharArray();
        String pkcs11cfg = properties.getProperty("PKCS11CFG");

		BouncyCastleProvider providerBC = new BouncyCastleProvider();
		Security.addProvider(providerBC);
		FileInputStream fis = new FileInputStream(pkcs11cfg);
		Provider providerPKCS11 = new SunPKCS11(fis);
        Security.addProvider(providerPKCS11);
        
        KeyStore ks = KeyStore.getInstance("PKCS11");
		ks.load(null, pass);
        String alias = (String)ks.aliases().nextElement();
        PrivateKey pk = (PrivateKey)ks.getKey(alias, pass);
        Certificate[] chain = ks.getCertificateChain(alias);
        OcspClient ocspClient = new OcspClientBouncyCastle();
        TSAClient 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 crlList = new ArrayList();
        crlList.add(new CrlClientOnline(chain));
        C4_01_SignWithPKCS11HSM app = new C4_01_SignWithPKCS11HSM();
		app.sign(SRC, DEST, chain, pk, DigestAlgorithms.SHA256, providerPKCS11.getName(), CryptoStandard.CMS,
				"HSM test", "Ghent", crlList, ocspClient, tsaClient, 0);
	}
}
C4_02_SignWithPKCS11USB.java
/*
 * This class is part of the white paper entitled
 * "Digital Signatures for PDF documents"
 * written by Bruno Lowagie
 * 
 * For more info, go to: http://itextpdf.com/learn
 */
package signatures.chapter4;

import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.Security;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

import sun.security.pkcs11.SunPKCS11;
import sun.security.pkcs11.wrapper.CK_C_INITIALIZE_ARGS;
import sun.security.pkcs11.wrapper.CK_TOKEN_INFO;
import sun.security.pkcs11.wrapper.PKCS11;
import sun.security.pkcs11.wrapper.PKCS11Exception;

import com.itextpdf.text.DocumentException;
import com.itextpdf.text.log.LoggerFactory;
import com.itextpdf.text.log.SysoLogger;
import com.itextpdf.text.pdf.security.CertificateUtil;
import com.itextpdf.text.pdf.security.CrlClient;
import com.itextpdf.text.pdf.security.CrlClientOnline;
import com.itextpdf.text.pdf.security.DigestAlgorithms;
import com.itextpdf.text.pdf.security.MakeSignature.CryptoStandard;
import com.itextpdf.text.pdf.security.OcspClient;
import com.itextpdf.text.pdf.security.OcspClientBouncyCastle;
import com.itextpdf.text.pdf.security.TSAClient;
import com.itextpdf.text.pdf.security.TSAClientBouncyCastle;

public class C4_02_SignWithPKCS11USB extends C4_01_SignWithPKCS11HSM {
	public static final String SRC = "src/main/resources/hello.pdf";
	public static final String DEST = "results/chapter4/hello_token.pdf";
	public static final String DLL = "c:/windows/system32/dkck201.dll";

	public static void main(String[] args) throws IOException, GeneralSecurityException, DocumentException {

		LoggerFactory.getInstance().setLogger(new SysoLogger());
		
		Properties properties = new Properties();
		properties.load(new FileInputStream("c:/home/blowagie/key.properties"));
        char[] pass = properties.getProperty("PASSWORD").toCharArray();

		String config = "name=ikey4000\n" +
				"library=" + DLL + "\n" +
				"slotListIndex = " + getSlotsWithTokens(DLL)[0];
		ByteArrayInputStream bais = new ByteArrayInputStream(config.getBytes());
		Provider providerPKCS11 = new SunPKCS11(bais);
        Security.addProvider(providerPKCS11);
        System.out.println(providerPKCS11.getName());
		BouncyCastleProvider providerBC = new BouncyCastleProvider();
		Security.addProvider(providerBC);
        
        KeyStore ks = KeyStore.getInstance("PKCS11");
		ks.load(null, pass);
        String alias = (String)ks.aliases().nextElement();
        PrivateKey pk = (PrivateKey)ks.getKey(alias, pass);
        Certificate[] chain = ks.getCertificateChain(alias);
        OcspClient ocspClient = new OcspClientBouncyCastle();
        TSAClient 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 crlList = new ArrayList();
        crlList.add(new CrlClientOnline(chain));
        C4_02_SignWithPKCS11USB app = new C4_02_SignWithPKCS11USB();
		app.sign(SRC, DEST, chain, pk, DigestAlgorithms.SHA256, providerPKCS11.getName(), CryptoStandard.CMS,
				"Test", "Ghent", crlList, ocspClient, tsaClient, 0);
	}
	
	
	public static long[] getSlotsWithTokens(String libraryPath) throws IOException{
        CK_C_INITIALIZE_ARGS initArgs = new CK_C_INITIALIZE_ARGS();
        String functionList = "C_GetFunctionList";
 
        initArgs.flags = 0;
        PKCS11 tmpPKCS11 = null;
        long[] slotList = null;
        try {
            try {
                tmpPKCS11 = PKCS11.getInstance(libraryPath, functionList, initArgs, false);
            } catch (IOException ex) {
                ex.printStackTrace();
                throw ex;
            }
        } catch (PKCS11Exception e) {
            try {
                initArgs = null;
                tmpPKCS11 = PKCS11.getInstance(libraryPath, functionList, initArgs, true);
            } catch (IOException ex) {
               ex.printStackTrace();
            } catch (PKCS11Exception ex) {
               ex.printStackTrace();
            }
        }
 
        try {
            slotList = tmpPKCS11.C_GetSlotList(true);
 
            for (long slot : slotList){
                CK_TOKEN_INFO tokenInfo = tmpPKCS11.C_GetTokenInfo(slot);
                System.out.println("slot: "+slot+"\nmanufacturerID: "
                        + String.valueOf(tokenInfo.manufacturerID) + "\nmodel: "
                        + String.valueOf(tokenInfo.model));
            }
        } catch (PKCS11Exception ex) {
                ex.printStackTrace();
        } catch (Throwable t) {
            t.printStackTrace();
        }
 
        return slotList;
 
    }
}
C4_03_SignWithPKCS11SC.java
/*
 * This class is part of the white paper entitled
 * "Digital Signatures for PDF documents"
 * written by Bruno Lowagie
 * 
 * For more info, go to: http://itextpdf.com/learn
 */
package signatures.chapter4;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.Security;
import java.security.cert.Certificate;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

import sun.security.pkcs11.SunPKCS11;

import com.itextpdf.text.DocumentException;
import com.itextpdf.text.log.LoggerFactory;
import com.itextpdf.text.log.SysoLogger;
import com.itextpdf.text.pdf.security.CrlClient;
import com.itextpdf.text.pdf.security.CrlClientOnline;
import com.itextpdf.text.pdf.security.DigestAlgorithms;
import com.itextpdf.text.pdf.security.MakeSignature.CryptoStandard;
import com.itextpdf.text.pdf.security.OcspClient;
import com.itextpdf.text.pdf.security.OcspClientBouncyCastle;

public class C4_03_SignWithPKCS11SC extends C4_02_SignWithPKCS11USB {
	public static final String SRC = "src/main/resources/hello.pdf";
	public static final String DEST = "results/chapter4/hello_smartcard_%s.pdf";
	public static final String DLL = "c:/windows/system32/beidpkcs11.dll";

	public static void main(String[] args) throws IOException, GeneralSecurityException, DocumentException {
		LoggerFactory.getInstance().setLogger(new SysoLogger());
		String config = "name=beid\n" +
				"library=" + DLL + "\n" +
				"slotListIndex = " + getSlotsWithTokens(DLL)[0];
		ByteArrayInputStream bais = new ByteArrayInputStream(config.getBytes());
		Provider providerPKCS11 = new SunPKCS11(bais);
        Security.addProvider(providerPKCS11);
		BouncyCastleProvider providerBC = new BouncyCastleProvider();
		Security.addProvider(providerBC);
        KeyStore ks = KeyStore.getInstance("PKCS11");
		ks.load(null, null);
		Enumeration aliases = ks.aliases();
		while (aliases.hasMoreElements()) {
			System.out.println(aliases.nextElement());
		}
		smartcardsign(providerPKCS11.getName(), ks, "Authentication");
		smartcardsign(providerPKCS11.getName(), ks, "Signature");
	}
	public static void smartcardsign(String provider, KeyStore ks, String alias) throws GeneralSecurityException, IOException, DocumentException {
        PrivateKey pk = (PrivateKey)ks.getKey(alias, null);
        Certificate[] chain = ks.getCertificateChain(alias);
        OcspClient ocspClient = new OcspClientBouncyCastle();
        List crlList = new ArrayList();
        crlList.add(new CrlClientOnline(chain));
        C4_03_SignWithPKCS11SC app = new C4_03_SignWithPKCS11SC();
		app.sign(SRC, String.format(DEST, alias), chain, pk, DigestAlgorithms.SHA256, provider, CryptoStandard.CMS,
				"Test", "Ghent", crlList, ocspClient, null, 0);
	}
}
C4_04_InspectBEID.java
package signatures.chapter4;

import java.io.FileOutputStream;
import java.io.IOException;

import javax.smartcardio.CardException;
import javax.smartcardio.CardTerminal;

import com.itextpdf.smartcard.CardReaders;
import com.itextpdf.smartcard.SmartCard;
import com.itextpdf.smartcard.beid.BeIDFileFactory;
import com.itextpdf.smartcard.beid.pojos.AddressPojo;
import com.itextpdf.smartcard.beid.pojos.IdentityPojo;
import com.itextpdf.smartcard.beid.pojos.PhotoPojo;

public class C4_04_InspectBEID {

	public static final String PHOTO = "results/chapter4/photo.jpg"; 
	
	public static void main(String[] args) throws CardException, IOException {
		CardReaders readers = new CardReaders();
		for (CardTerminal terminal : readers.getReaders()) {
			System.out.println(terminal.getName());
		}
		for (CardTerminal terminal : readers.getReadersWithCard()) {
			System.out.println(terminal.getName());
			SmartCard card = new SmartCard(terminal);
			IdentityPojo id = BeIDFileFactory.getIdentity(card);
			System.out.println(id.toString());
			AddressPojo address = BeIDFileFactory.getAddress(card);
			System.out.println(address);
			PhotoPojo photo = BeIDFileFactory.getPhoto(card);
			FileOutputStream fos = new FileOutputStream(PHOTO);
			fos.write(photo.getPhoto());
			fos.flush();
			fos.close();
		}
	} 
}
C4_05_SignWithBEID.java
package signatures.chapter4;

import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.cert.X509Certificate;

import javax.crypto.Cipher;
import javax.smartcardio.CardException;
import javax.smartcardio.CardTerminal;

import com.itextpdf.smartcard.CardReaders;
import com.itextpdf.smartcard.PinDialog;
import com.itextpdf.smartcard.SmartCardWithKey;
import com.itextpdf.smartcard.beid.BeIDCertificates;

public class C4_05_SignWithBEID {

	public static void main(String[] args) throws CardException, IOException, GeneralSecurityException {
		CardReaders readers = new CardReaders();
		for (CardTerminal terminal : readers.getReadersWithCard()) {
			SmartCardWithKey card = new SmartCardWithKey(terminal, BeIDCertificates.AUTHENTICATION_KEY_ID, "RSA");
			card.setPinProvider(new PinDialog(4));
			byte[] signed = card.sign("ABCD".getBytes(), "SHA-256");
			System.out.println(new String(signed));
			X509Certificate cert = card.readCertificate(BeIDCertificates.AUTHN_CERT_FILE_ID);
			Cipher cipher = Cipher.getInstance("RSA");
			cipher.init(Cipher.DECRYPT_MODE, cert.getPublicKey());
			System.out.println(new String(cipher.doFinal(signed)));
		}
	} 
}
C4_06_SignWithBEID.java
package signatures.chapter4;

import java.io.FileOutputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.Security;
import java.security.cert.Certificate;
import java.util.ArrayList;
import java.util.Collection;

import javax.smartcardio.CardException;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

import com.itextpdf.smartcard.CardReaders;
import com.itextpdf.smartcard.EidSignature;
import com.itextpdf.smartcard.SmartCardWithKey;
import com.itextpdf.smartcard.beid.BeIDCard;
import com.itextpdf.smartcard.beid.BeIDCertificates;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.log.LoggerFactory;
import com.itextpdf.text.log.SysoLogger;
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.CrlClient;
import com.itextpdf.text.pdf.security.CrlClientOnline;
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.OcspClient;
import com.itextpdf.text.pdf.security.OcspClientBouncyCastle;
import com.itextpdf.text.pdf.security.TSAClient;
import com.itextpdf.text.pdf.security.MakeSignature.CryptoStandard;

public class C4_06_SignWithBEID {

	public static final String SRC = "src/main/resources/hello.pdf";
	public static final String DEST = "results/chapter4/hello_beid.pdf";

	public void sign(String src, String dest,
			SmartCardWithKey card, Certificate[] chain,
			CryptoStandard subfilter,
			String reason, String location,
			Collection crlList,
			OcspClient ocspClient,
			TSAClient tsaClient,
			int estimatedSize)
					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
        ExternalSignature eid = new EidSignature(card, "SHA256", "BC");
        ExternalDigest digest = new BouncyCastleDigest();
        MakeSignature.signDetached(appearance, digest, eid, chain, crlList, ocspClient, tsaClient, estimatedSize, subfilter);
	}
	
	public static void main(String[] args) throws CardException, GeneralSecurityException, IOException, DocumentException {
		LoggerFactory.getInstance().setLogger(new SysoLogger());
		
		BouncyCastleProvider provider = new BouncyCastleProvider();
		Security.addProvider(provider);
		
		CardReaders readers = new CardReaders();
		SmartCardWithKey card = new BeIDCard(readers.getReadersWithCard().get(0));
		card.setSecure(true);
		Certificate[] chain = BeIDCertificates.getSignCertificateChain(card);
		Collection crlList = new ArrayList();
		crlList.add(new CrlClientOnline(chain));
        OcspClient ocspClient = new OcspClientBouncyCastle();
		C4_06_SignWithBEID app = new C4_06_SignWithBEID();
		app.sign(SRC, DEST, card, chain, CryptoStandard.CMS,
				"Test", "Ghent", crlList, ocspClient, null, 0);
	}
}
C4_07_ClientServerSigning.java
package signatures.chapter4;

import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.GeneralSecurityException;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;

import com.itextpdf.text.DocumentException;
import com.itextpdf.text.ExceptionConverter;
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;

public class C4_07_ClientServerSigning {

	public static final String SRC = "src/main/resources/hello.pdf";
	public static final String DEST = "results/chapter4/hello_server.pdf";

	public static final String CERT = "http://demo.itextsupport.com/SigningApp/itextpdf.cer";
	
	public class ServerSignature implements ExternalSignature {
		public static final String SIGN = "http://demo.itextsupport.com/SigningApp/signbytes";
		
		public String getHashAlgorithm() {
			return DigestAlgorithms.SHA256;
		}

		public String getEncryptionAlgorithm() {
			return "RSA";
		}

		public byte[] sign(byte[] message) throws GeneralSecurityException {
			try {
				URL url = new URL(SIGN);
				HttpURLConnection conn = (HttpURLConnection)url.openConnection();
			    conn.setDoOutput(true);
			    conn.setRequestMethod("POST"); 
			    conn.connect();
			    OutputStream os = conn.getOutputStream();
			    os.write(message);
			    os.flush();
			    os.close();
			    InputStream is = conn.getInputStream();
			    ByteArrayOutputStream baos = new ByteArrayOutputStream();
		        byte[] b = new byte[1];  
		        int read;  
		        while ((read = is.read(b)) != -1) {  
		            baos.write(b, 0, read);  
		        }
			    is.close();
				return baos.toByteArray();
			} catch (IOException e) {
				throw new ExceptionConverter(e);
			}
		}
		
	}
	
	public void sign(String src, String dest,
			Certificate[] chain,
			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 ServerSignature();
        MakeSignature.signDetached(appearance, digest, signature, chain, null, null, null, 0, subfilter);
	}
	
	public static void main(String[] args) throws GeneralSecurityException, IOException, DocumentException {
		CertificateFactory factory = CertificateFactory.getInstance("X.509");
		URL certUrl = new URL(CERT);
		Certificate[] chain = new Certificate[1];
		chain[0] = factory.generateCertificate(certUrl.openStream());
		C4_07_ClientServerSigning app = new C4_07_ClientServerSigning();
		app.sign(SRC, DEST, chain, CryptoStandard.CMS, "Test", "Ghent");
	}
}
C4_08_ServerClientSigning.java
package signatures.chapter4;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Signature;
import java.util.List;

public class C4_08_ServerClientSigning {

	public static final String CERT = "src/main/resources/bruno.crt";
	public static final String KEYSTORE = "src/main/resources/ks";
	public static final char[] PASSWORD = "password".toCharArray();
	public static final String DEST = "results/chapter4/hello_server2.pdf";

	public static final String PRE = "http://demo.itextsupport.com/SigningApp/presign";
	public static final String POST = "http://demo.itextsupport.com/SigningApp/postsign";
	
	public static void main(String[] args) throws IOException, GeneralSecurityException {
		// we make a connection to a PreSign servlet
		URL url = new URL(PRE);
		HttpURLConnection conn = (HttpURLConnection)url.openConnection();
	    conn.setDoOutput(true);
	    conn.setRequestMethod("POST"); 
	    conn.connect();
	    // we upload our self-signed certificate
	    OutputStream os = conn.getOutputStream();
	    FileInputStream fis = new FileInputStream(CERT);
		int read;
		byte[] data = new byte[256];
		while ((read = fis.read(data, 0, data.length)) != -1) {
			os.write(data, 0, read);
		}
	    os.flush();
	    os.close();
	    // we use cookies to maintain a session
		List cookies = conn.getHeaderFields().get("Set-Cookie");
	    // we receive a hash that needs to be signed
	    InputStream is = conn.getInputStream();
	    ByteArrayOutputStream baos = new ByteArrayOutputStream();
	    data = new byte[256];
        while ((read = is.read(data)) != -1) {  
            baos.write(data, 0, read);  
        }
	    is.close();
	    byte[] hash = baos.toByteArray();
	    
	    // we load our private key from the key store
		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);
        // we sign the hash received from the server
		Signature sig = Signature.getInstance("SHA256withRSA");
		sig.initSign(pk);
		sig.update(hash);
		data = sig.sign();
		
		// we make a connection to the PostSign Servlet
		url = new URL(POST);
		conn = (HttpURLConnection)url.openConnection();
		for (String cookie : cookies) {
		    conn.addRequestProperty("Cookie", cookie.split(";", 2)[0]);
		}
	    conn.setDoOutput(true);
	    conn.setRequestMethod("POST"); 
	    conn.connect();
	    // we upload the signed bytes
	    os = conn.getOutputStream();
	    os.write(data);
	    os.flush();
	    os.close();
	    // we receive the signed document
	    is = conn.getInputStream();
	    FileOutputStream fos = new FileOutputStream(DEST);
	    data = new byte[256];
        while ((read = is.read(data)) != -1) {  
            fos.write(data, 0, read);  
        }
	    is.close();
	    fos.flush();
	    fos.close();
	}
}
C4_09_DeferredSigning.java
package signatures.chapter4;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
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 org.bouncycastle.jce.provider.BouncyCastleProvider;

import com.itextpdf.text.DocumentException;
import com.itextpdf.text.ExceptionConverter;
import com.itextpdf.text.Rectangle;
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.PdfStamper;
import com.itextpdf.text.pdf.security.BouncyCastleDigest;
import com.itextpdf.text.pdf.security.DigestAlgorithms;
import com.itextpdf.text.pdf.security.ExternalBlankSignatureContainer;
import com.itextpdf.text.pdf.security.ExternalSignatureContainer;
import com.itextpdf.text.pdf.security.MakeSignature;
import com.itextpdf.text.pdf.security.MakeSignature.CryptoStandard;
import com.itextpdf.text.pdf.security.PdfPKCS7;
import com.itextpdf.text.pdf.security.PrivateKeySignature;

public class C4_09_DeferredSigning {
	public static final String CERT = "src/main/resources/bruno.crt";
	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/chapter4/hello_empty_sig.pdf";
	public static final String DEST = "results/chapter4/hello_sig_ok.pdf";

	class MyExternalSignatureContainer implements ExternalSignatureContainer {

		protected PrivateKey pk;
		protected Certificate[] chain;
		
		public MyExternalSignatureContainer(PrivateKey pk, Certificate[] chain) {
			this.pk = pk;
			this.chain = chain;
		}
		
		public byte[] sign(InputStream is) throws GeneralSecurityException {
			try {
				PrivateKeySignature signature = new PrivateKeySignature(pk, "SHA256", "BC");
				String hashAlgorithm = signature.getHashAlgorithm();
				BouncyCastleDigest digest = new BouncyCastleDigest();
				PdfPKCS7 sgn = new PdfPKCS7(null, chain, hashAlgorithm, null, digest, false);
		        byte hash[] = DigestAlgorithms.digest(is, digest.getMessageDigest(hashAlgorithm));
				Calendar cal = Calendar.getInstance();
		        byte[] sh = sgn.getAuthenticatedAttributeBytes(hash, cal, null, null, CryptoStandard.CMS);
		        byte[] extSignature = signature.sign(sh);
		        sgn.setExternalDigest(extSignature, null, signature.getEncryptionAlgorithm());
				return sgn.getEncodedPKCS7(hash, cal, null, null, null, CryptoStandard.CMS);
			}
			catch (IOException ioe) {
				throw new ExceptionConverter(ioe);
			}
		}

		public void modifySigningDictionary(PdfDictionary signDic) {
		}
		
	}
	
	public void emptySignature(String src, String dest, String fieldname, Certificate[] chain) throws IOException, DocumentException, GeneralSecurityException {
		PdfReader reader = new PdfReader(src);
        FileOutputStream os = new FileOutputStream(dest);
        PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0');
        PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
        appearance.setVisibleSignature(new Rectangle(36, 748, 144, 780), 1, fieldname);
        appearance.setCertificate(chain[0]);
		ExternalSignatureContainer external = new ExternalBlankSignatureContainer(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED);
		MakeSignature.signExternalContainer(appearance, external, 8192);
	}
	
	public void createSignature(String src, String dest, String fieldname, PrivateKey pk, Certificate[] chain) throws IOException, DocumentException, GeneralSecurityException {
        
		PdfReader reader = new PdfReader(src);
        FileOutputStream os = new FileOutputStream(dest);
        ExternalSignatureContainer external = new MyExternalSignatureContainer(pk, chain);
        MakeSignature.signDeferred(reader, fieldname, os, external);
	}
	
	public static void main(String[] args) throws IOException, GeneralSecurityException, DocumentException {
		BouncyCastleProvider providerBC = new BouncyCastleProvider();
		Security.addProvider(providerBC);

	    // we load our private key from the key store
		KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
		ks.load(new FileInputStream(KEYSTORE), PASSWORD);
        String alias = (String)ks.aliases().nextElement();
        Certificate[] chain = ks.getCertificateChain(alias);
        PrivateKey pk = (PrivateKey) ks.getKey(alias, PASSWORD);
		
		C4_09_DeferredSigning app = new C4_09_DeferredSigning();
		app.emptySignature(SRC, TEMP, "sig", chain);
		app.createSignature(TEMP, DEST, "sig", pk, chain);
	}
}
C4_03_SignWithPKCS11SC.cs
/*
 * This class is part of the white paper entitled
 * "Digital Signatures for PDF documents"
 * written by Bruno Lowagie
 * 
 * For more info, go to: http://itextpdf.com/learn
 */

using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography.X509Certificates;
using Cryptware.NCryptoki;
using Org.BouncyCastle.Security;
using iTextSharp.text;
using iTextSharp.text.log;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.security;
using X509Certificate = Org.BouncyCastle.X509.X509Certificate;

namespace signatures.chapter4 {
    class CryptokiPrivateKeySignature : IExternalSignature
    {
        private readonly Session session;
        RSAPrivateKey privateKey;

        public CryptokiPrivateKeySignature(Session session, String alias) {
            this.session = session;
            CryptokiCollection template = new CryptokiCollection();
            template.Add(new ObjectAttribute(ObjectAttribute.CKA_CLASS, CryptokiObject.CKO_PRIVATE_KEY));
            template.Add(new ObjectAttribute(ObjectAttribute.CKA_KEY_TYPE, Key.CKK_RSA));
            template.Add(new ObjectAttribute(ObjectAttribute.CKA_LABEL, alias));
            privateKey = (RSAPrivateKey)session.Objects.Find(template);
        }

        public String GetHashAlgorithm() {
            return "SHA1";
        }
        
        public String GetEncryptionAlgorithm() {
            return "RSA";
        }

        public byte[] Sign(byte[] message) {
            session.SignInit(Mechanism.SHA1_RSA_PKCS, privateKey);
            return session.Sign(message);
        }
    }

    class C4_03_SignWithPKCS11SC {
        public const String SRC = "../../../../resources/hello.pdf";
	    public const String DEST = "../../../../results/chapter4/hello_smartcard_{0}.pdf";
	    public const String DLL = "c:/windows/system32/beidpkcs11.dll";

        public void Sign(String src, String dest, ICollection chain, Session session, String alias,
                         String digestAlgorithm, CryptoStandard subfilter, String reason, String location,
                         ICollection crlList, IOcspClient ocspClient, ITSAClient tsaClient, int estimatedSize) {
            // Creating the reader and the stamper
            PdfReader reader = null;
            PdfStamper stamper = null;
            FileStream os = null;
            try {
                reader = new PdfReader(src);
                os = new FileStream(dest, FileMode.Create);
                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 CryptokiPrivateKeySignature(session, alias);
                MakeSignature.SignDetached(appearance, pks, chain, crlList, ocspClient, tsaClient, estimatedSize, subfilter);
            } finally {
                if (reader != null)
                    reader.Close();
                if (stamper != null)
                    stamper.Close();
                if (os != null)
                    os.Close();
            }
        }

	    static void Main(String[] args) {
		    LoggerFactory.GetInstance().SetLogger(new SysoLogger());

            // Creates a Cryptoki object related to the specific PKCS#11 native library
            Cryptoki cryptoki = new Cryptoki("beidpkcs11.dll");
            cryptoki.Initialize();
            

            // Reads the set of slots containing a token
            SlotList slots = cryptoki.Slots;
            if(slots.Count == 0) {
               Console.WriteLine("No slot available");
               return;
            }
            // Gets the first slot available
            Slot slot = slots[0];
            if(!slot.IsTokenPresent) {
                Console.WriteLine("No token inserted in the slot: " + slots[0].Info.Description);
                return;
            }

            // Gets the first token available
            Token token = slot.Token;

            // Opens a read/write serial session
            Session session = 
                token.OpenSession(Session.CKF_SERIAL_SESSION | Session.CKF_RW_SESSION, null, null);

            // Executes the login passing the user PIN
            //int nRes = session.Login(Session.CKU_USER, "0000");
            /*if (nRes != 0) {
                Console.WriteLine("Wrong PIN");
                return;
            }*/

		    Smartcardsign(session, "Authentication");
            Smartcardsign(session, "Signature");
            
            // Logouts and closes the session
            session.Logout();
            session.Close();
            cryptoki.Finalize(IntPtr.Zero);
	    }

        public static void Smartcardsign(Session session, String alias) {
            // Searchs for an RSA certificate object
            // Sets the template with its attributes
            CryptokiCollection template = new CryptokiCollection();
            template.Add(new ObjectAttribute(ObjectAttribute.CKA_CLASS, CryptokiObject.CKO_CERTIFICATE));
            template.Add(new ObjectAttribute(ObjectAttribute.CKA_CERTIFICATE_TYPE, Certificate.CKC_X_509));
            template.Add(new ObjectAttribute(ObjectAttribute.CKA_LABEL, alias));

            Cryptware.NCryptoki.X509Certificate nCert = (Cryptware.NCryptoki.X509Certificate)session.Objects.Find(template);
            
            X509Certificate2 cert = Utils.ConvertCertificate(nCert);
            ICollection chain = new List();
            X509Chain x509chain = new X509Chain();
            x509chain.Build(cert);

            foreach (X509ChainElement x509ChainElement in x509chain.ChainElements) {
                chain.Add(DotNetUtilities.FromX509Certificate(x509ChainElement.Certificate));
            }

            IOcspClient ocspClient = new OcspClientBouncyCastle();
            List crlList = new List();
            crlList.Add(new CrlClientOnline(chain));
            C4_03_SignWithPKCS11SC app = new C4_03_SignWithPKCS11SC();
		    app.Sign(SRC, String.Format(DEST, alias), chain, session, alias, DigestAlgorithms.SHA256, CryptoStandard.CMS,
				    "Test", "Ghent", crlList, ocspClient, null, 0);
	    }
    }
}
C4_07_ClientServerSigning.cs
/*
 * This class is part of the white paper entitled
 * "Digital Signatures for PDF documents"
 * written by Bruno Lowagie
 * 
 * For more info, go to: http://itextpdf.com/learn
 */

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

namespace signatures.chapter4 {
    class C4_07_ClientServerSigning {
        public const String SRC = "../../../../resources/hello.pdf";
        public const String DEST = "../../../../results/chapter4/hello_server.pdf";

	    public const String CERT = "http://demo.itextsupport.com/SigningApp/itextpdf.cer";
    	
	    public class ServerSignature : IExternalSignature {
		    public const String SIGN = "http://demo.itextsupport.com/SigningApp/signbytes";
    		
		    public String GetHashAlgorithm() {
			    return DigestAlgorithms.SHA256;
		    }

		    public String GetEncryptionAlgorithm() {
			    return "RSA";
		    }

		    public byte[] Sign(byte[] message) {
                MemoryStream baos = new MemoryStream();
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(SIGN);
		        request.Method = "POST";
		        Stream ostream = request.GetRequestStream();
		        ostream.Write(message, 0, message.Length);
		        ostream.Close();
		        HttpWebResponse response = (HttpWebResponse)request.GetResponse();
		        Stream istream = response.GetResponseStream();
		        byte[] b = new byte[0x1000];
	            int read;  
	            while ((read = istream.Read(b, 0, b.Length)) != 0)  
	                baos.Write(b, 0, read);
		        istream.Close();
                return baos.ToArray();
		    }
    		
	    }
    	
	    public void Sign(String src, String dest, ICollection chain,
			    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 signature = new ServerSignature();
            MakeSignature.SignDetached(appearance, signature, chain, null, null, null, 0, subfilter);
	    }
    	
	    public static void Main(String[] args) {
            X509CertificateParser parser = new X509CertificateParser();
            Stream url = WebRequest.Create(CERT).GetResponse().GetResponseStream();
            ICollection chain = new List();
		    chain.Add(parser.ReadCertificate(url));
		    C4_07_ClientServerSigning app = new C4_07_ClientServerSigning();
		    app.Sign(SRC, DEST, chain, CryptoStandard.CMS, "Test", "Ghent");
	    }
    }
}
C4_08_ServerClientSigning.cs
/*
 * This class is part of the white paper entitled
 * "Digital Signatures for PDF documents"
 * written by Bruno Lowagie
 * 
 * For more info, go to: http://itextpdf.com/learn
 */

using System;
using System.IO;
using System.Net;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Security;

namespace signatures.chapter4 {
    class C4_08_ServerClientSigning {
        public const String CERT = "../../../../resources/bruno.crt";
	    public const String KEYSTORE = "../../../../resources/pkcs12";
	    public static char[] PASSWORD = "password".ToCharArray();
	    public const String DEST = "../../../../results/chapter4/hello_server2.pdf";

	    public const String PRE = "http://demo.itextsupport.com/SigningApp/presign";
	    public const String POST = "http://demo.itextsupport.com/SigningApp/postsign";
    	
	    public static void Main(String[] args) {
		    // we make a connection to a PreSign servlet
		    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(PRE);
	        request.Method = "POST";
	        // we upload our self-signed certificate
	        Stream os = request.GetRequestStream();
	        FileStream fis = new FileStream(CERT, FileMode.Open);
		    int read;
		    byte[] data = new byte[0x100];
		    while ((read = fis.Read(data, 0, data.Length)) != 0)
			    os.Write(data, 0, read);
	        os.Flush();
	        os.Close();
	        
	        HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            // we use cookies to maintain a session
	        String cookies = response.Headers["Set-Cookie"];
	        // we receive a hash that needs to be signed
	        Stream istream = response.GetResponseStream();
	        MemoryStream baos = new MemoryStream();
	        data = new byte[0x100];
            while ((read = istream.Read(data, 0, data.Length)) != 0)  
                baos.Write(data, 0, read);  
            istream.Close();
	        byte[] hash = baos.ToArray();
    	    
	        // we load our private key from the key store
            Pkcs12Store store = new Pkcs12Store(new FileStream(KEYSTORE, FileMode.Open), PASSWORD);
            String alias = "";
            // 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);

            // we sign the hash received from the server
            ISigner sig = SignerUtilities.GetSigner("SHA256withRSA");
		    sig.Init(true, pk.Key);
            sig.BlockUpdate(hash, 0, hash.Length);
            data = sig.GenerateSignature();
    		
		    // we make a connection to the PostSign Servlet
            request = (HttpWebRequest)WebRequest.Create(POST);
            request.Headers.Add(HttpRequestHeader.Cookie,cookies.Split(";".ToCharArray(), 2)[0]);
	        request.Method = "POST";
	        // we upload the signed bytes
	        os = request.GetRequestStream();
	        os.Write(data, 0, data.Length);
	        os.Flush();
	        os.Close();

	        // we receive the signed document
            response = (HttpWebResponse)request.GetResponse();
	        istream = response.GetResponseStream();
	        FileStream fos = new FileStream(DEST, FileMode.Create);
	        data = new byte[0x100];
            while ((read = istream.Read(data, 0, data.Length)) != 0)
                fos.Write(data, 0, read);
	        istream.Close();
	        fos.Flush();
	        fos.Close();
	    }
    }
}
Contact

Still have questions? 

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

Contact us
Stay updated

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

Subscribe Now