Digital signatures - chapter 4

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

Files: 
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<CrlClient> 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<CrlClient> crlList = new ArrayList<CrlClient>();
        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);
	}
}
/*
 * 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<CrlClient> crlList = new ArrayList<CrlClient>();
        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;
 
    }
}
/*
 * 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<String> 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<CrlClient> crlList = new ArrayList<CrlClient>();
        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);
	}
}
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();
		}
	} 
}
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)));
		}
	} 
}
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<CrlClient> 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<CrlClient> crlList = new ArrayList<CrlClient>();
		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);
	}
}
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");
	}
}
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<String> 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();
	}
}
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);
	}
}