Attached you'll find 2 file:

signAndTimestamp.java: just contains the method that performs signature and
timestamp
TimeStampService.java: contains the code used to send the timestamp request
to the timestamp server

I've attached both files, so that users can be able to get a full working
example.
Let me know if you need something else.

Regards,
Massimiliano Ziccardi
    private static void signAndTimestamp(File fIn, File fOut, File KeyStoreFile, String sKeyStorePassword, String sPrivateKeyLabel, String sCertificateChainAlias)
    {
        try
        {
            Security.addProvider(new BouncyCastleProvider());
            
            // Load the keys from the keystore.
            KeyStore ks = KeyStore.getInstance("PKCS12", new BouncyCastleProvider());
            ks.load(new FileInputStream(KeyStoreFile), sKeyStorePassword.toCharArray());
            PrivateKey privKey = (PrivateKey) ks.getKey(sPrivateKeyLabel, sKeyStorePassword.toCharArray());
            Certificate[] certChain = ks.getCertificateChain(sCertificateChainAlias);

            PdfReader reader = new PdfReader(fIn.getAbsolutePath());
            PdfStamper stp = PdfStamper.createSignature(reader, new FileOutputStream(fOut), '\0');
            PdfSignatureAppearance sap = stp.getSignatureAppearance();
            sap.setVisibleSignature(new Rectangle(100, 100, 300, 200), 1, null);
            // If you have a labeled signature field, use the following line instead of the previous one
            // sap.setVisibleSignature("SIGNATURE_FIELD_NAME"); 
            sap.setCrypto(null, certChain, null, null);
            sap.setReason("I like to sign");
            sap.setLocation("Universe");
            sap.setAcro6Layers(true);
            sap.setRender(PdfSignatureAppearance.SignatureRenderNameAndDescription);
            PdfSignature dic = new PdfSignature(PdfName.ADOBE_PPKMS, PdfName.ADBE_PKCS7_SHA1);
            dic.setDate(new PdfDate(sap.getSignDate()));
            dic.setName(PdfPKCS7.getSubjectFields((X509Certificate) certChain[0]).getField("CN"));
            if (sap.getReason() != null)
                dic.setReason(sap.getReason());
            if (sap.getLocation() != null)
                dic.setLocation(sap.getLocation());
            sap.setCryptoDictionary(dic);
            
            // 8000 bytes should be enough to contain the signature. If you get errors about a too small buffer, resize this accordingly
            int csize = 8000;
            HashMap exc = new HashMap();
            exc.put(PdfName.CONTENTS, new Integer(csize * 2 + 2));
            sap.preClose(exc);

            MessageDigest md = MessageDigest.getInstance("SHA1");
            InputStream s = sap.getRangeStream();
            int read = 0;
            byte[] buff = new byte[8192];
            while ((read = s.read(buff, 0, 8192)) > 0)
            {
                md.update(buff, 0, read);
            }

            byte[] hash = md.digest();

            CMSSignedDataGenerator generator = new CMSSignedDataGenerator();

            // Create an AttributeTableGenerator to create the signature timestamp token
            CMSAttributeTableGenerator unsignedAttributeTableGenerator = new CMSAttributeTableGenerator()
            {

                public AttributeTable getAttributes(final Map parameters) throws CMSAttributeTableGenerationException
                {
                    AttributeTable attributeTable = null;

                    // Gets the signature bytes
                    byte[] signatureBytes = (byte[]) parameters.get(SIGNATURE);

                    DERObject obj;
                    try
                    {
                        // digests the signature
                        MessageDigest d = MessageDigest.getInstance("SHA1");
                        byte[] signatureHash = d.digest(signatureBytes);
                        
                        // Sends the request to the timestamp server
                        TimeStampService tss = new TimeStampService(TIMESTAMP_SERVER_URL, TIMESTAMP_SERVER_PORT, TIMESTAMP_POLICY_OID);
                        obj = new ASN1InputStream(tss.requestTimeStamp(signatureHash).getEncoded()).readObject();
                        
                        // Creates the signatureTimestampToken attribute
                        DERSet s = new DERSet(obj);
                        Attribute att = new Attribute(TimeStampService.id_signatureTimeStampToken, s);
                        Hashtable oh = new Hashtable();
                        oh.put(TimeStampService.id_signatureTimeStampToken, att);
                        attributeTable = new AttributeTable(oh);

                        return attributeTable;                        
                    }
                    catch (Exception e)
                    {
                        throw new CMSAttributeTableGenerationException(e.getMessage(),  e);
                    }
                }
            };

            generator.addSigner(privKey, (X509Certificate) certChain[0], CMSSignedDataGenerator.DIGEST_SHA1, new DefaultSignedAttributeTableGenerator(), unsignedAttributeTableGenerator);

            List chainAndCrls = new ArrayList();
            
            if (certChain != null)
                chainAndCrls.addAll(Arrays.asList(certChain));

            // If you have crls:
            // if (crls != null)
            //   chainAndCrls.addAll(Arrays.asList(crls); 

            CertStore chainStore = CertStore.getInstance("Collection", new CollectionCertStoreParameters(chainAndCrls), "BC");
            generator.addCertificatesAndCRLs(chainStore);
            
            CMSProcessable content = new CMSProcessableByteArray(hash);
            CMSSignedData signedData = generator.generate(content, true, "BC");

            byte[] signedDataDerBytes = signedData.getEncoded();
            byte[] outc = new byte[csize];
            
            PdfDictionary dic2 = new PdfDictionary();

            System.arraycopy(signedDataDerBytes, 0, outc, 0, signedDataDerBytes.length);
            
            dic2.put(PdfName.CONTENTS, new PdfString(outc).setHexWriting(true));

            sap.close(dic2);
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

package it.security.timestamp;


import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;

import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.DERInteger;
import org.bouncycastle.asn1.DERObjectIdentifier;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.cms.CMSException;
import org.bouncycastle.cms.CMSSignedData;
import org.bouncycastle.tsp.TSPAlgorithms;
import org.bouncycastle.tsp.TSPException;
import org.bouncycastle.tsp.TimeStampRequest;
import org.bouncycastle.tsp.TimeStampRequestGenerator;
import org.bouncycastle.tsp.TimeStampToken;

/**
 * This object implements the timestamp protocol
 * .
 * @author Massimiliano Ziccardi
 *
 */
public class TimeStampService
{
    /**
     * The OID of the signature timestamp token
     */
    public static final DERObjectIdentifier id_signatureTimeStampToken = new DERObjectIdentifier("1.2.840.113549.1.9.16.2.14");
   
	/**
	 * The Policy OID
	 */
	private String m_sPolicyOID = null;

	/**
	 * The hostname or IP address of the Timestamp Server
	 */
	private String m_sHost = null;

	/**
	 * The port of the Timestamp Server. Default is 318.
	 */
	private int m_iPort = 318;

	/**
	 * Instantiate and initializes the timestamp service object
	 * @param sHostname The hostname or IP address of the Timestamp Server
	 * @param iPort The port of the Timestamp Server. Default is 318.
	 * @param sPolicyOID The Policy OID
	 */
	public TimeStampService(final String sHostname, final int iPort, final String sPolicyOID)
	{
		super();
		m_sHost = sHostname;
		m_iPort  = iPort;
		m_sPolicyOID = sPolicyOID;
	}
	
	/**
	 * Sends the timestamp request to the timestamp server and
	 * returns the received TimeStampToken
	 * 
	 * @param digest - the data to be timestamped
	 * @return the time stamp generated by the time stamp server.
	 * @throws TSPException - on any timestamp error
	 * @throws IOException 
	 */
    public TimeStampToken requestTimeStamp(final byte digest[])
        throws TSPException, IOException
    {
			TimeStampRequestGenerator reqgen = new TimeStampRequestGenerator();
			reqgen.setReqPolicy(m_sPolicyOID);
			TimeStampRequest req = reqgen.generate(TSPAlgorithms.SHA1, digest);
			byte request[] = req.getEncoded();
			
			int length = request.length + 1;
			Socket s = new Socket(m_sHost, m_iPort);
			s.setSoTimeout(5000);
			
			OutputStream os = s.getOutputStream();
			os.write((byte) (length >> 24));
			os.write((byte) (length >> 16));
			os.write((byte) (length >> 8));
			os.write((byte) length);
			os.write(0);
			os.write(request);
			DataInputStream is = new DataInputStream(s.getInputStream());
			length = is.readInt() - 1;
			
			if (is.readByte() == 10)
			{
				is.readChar();
				length -= 2;
			}
			
			byte response[] = new byte[length];
            is.readFully(response);
            s.close();
            
            ASN1InputStream in = new ASN1InputStream(response);
            DERSequence asn = (DERSequence) in.readObject();
            
            DERSequence info = (DERSequence)asn.getObjectAt(0);
            DERInteger status = (DERInteger)info.getObjectAt(0);
            
            if(status.getValue().intValue() != 0 && status.getValue().intValue() != 1) throw new TSPException("Timestamp server error");
            
            try
			{
				return new TimeStampToken(new CMSSignedData(asn.getObjectAt(1).getDERObject().getDEREncoded()));
			}
			catch (TSPException e)
			{
				throw e;
			}
			catch (Exception e)
			{
				throw new TSPException(e.getMessage(), e);
			}
    }
   
 
}
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
iText-questions mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/itext-questions

Buy the iText book: http://www.1t3xt.com/docs/book.php

Reply via email to