Skip to main content
Skip table of contents

Digital signatures - chapter 4

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


c4_03_signwithpkcs11sc

JAVA

JAVA
/*
 * This class is part of the white paper entitled
 * "Digital Signatures for PDF documents"
 * written by Bruno Lowagie
 * 
 * For more info, go to: http://itextpdf.com/learn
 */
package signatures.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);
	}
}

C#

C#
/*
 * This class is part of the white paper entitled
 * "Digital Signatures for PDF documents"
 * written by Bruno Lowagie
 * 
 * For more info, go to: http://itextpdf.com/learn
 */

using System;
using System.Collections.Generic;
using System.IO;
using 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<X509Certificate> chain, Session session, String alias,
                         String digestAlgorithm, CryptoStandard subfilter, String reason, String location,
                         ICollection<ICrlClient> 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<X509Certificate> chain = new List<X509Certificate>();
            X509Chain x509chain = new X509Chain();
            x509chain.Build(cert);

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

            IOcspClient ocspClient = new OcspClientBouncyCastle();
            List<ICrlClient> crlList = new List<ICrlClient>();
            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

JAVA

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");
	}
}

C#

C#
/*
 * This class is part of the white paper entitled
 * "Digital Signatures for PDF documents"
 * written by Bruno Lowagie
 * 
 * For more info, go to: http://itextpdf.com/learn
 */

using System;
using System.Collections.Generic;
using System.IO;
using 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<X509Certificate> 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<X509Certificate> chain = new List<X509Certificate>();
		    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

JAVA

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<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();
	}
}

C#

C#
/*
 * This class is part of the white paper entitled
 * "Digital Signatures for PDF documents"
 * written by Bruno Lowagie
 * 
 * For more info, go to: http://itextpdf.com/learn
 */

using System;
using System.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();
	    }
    }
}
JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.