View Javadoc

1   package org.eparapher.core.crypto.timestamp;
2   
3   import java.io.ByteArrayInputStream;
4   import java.io.InputStream;
5   import java.math.BigInteger;
6   import java.security.KeyStore;
7   import java.security.PrivateKey;
8   import java.security.SecureRandom;
9   import java.security.cert.CertStore;
10  import java.security.cert.CollectionCertStoreParameters;
11  import java.security.cert.X509Certificate;
12  import java.util.ArrayList;
13  import java.util.Collection;
14  import java.util.Date;
15  import java.util.Iterator;
16  
17  import org.apache.commons.httpclient.HttpClient;
18  import org.apache.commons.httpclient.methods.PostMethod;
19  import org.apache.log4j.Logger;
20  import org.bouncycastle.asn1.ASN1InputStream;
21  import org.bouncycastle.asn1.DEREncodableVector;
22  import org.bouncycastle.asn1.DERObject;
23  import org.bouncycastle.asn1.DERObjectIdentifier;
24  import org.bouncycastle.asn1.DERSet;
25  import org.bouncycastle.asn1.cms.Attribute;
26  import org.bouncycastle.asn1.cms.AttributeTable;
27  import org.bouncycastle.cms.CMSSignedData;
28  import org.bouncycastle.cms.SignerId;
29  import org.bouncycastle.cms.SignerInformation;
30  import org.bouncycastle.cms.SignerInformationStore;
31  import org.bouncycastle.tsp.TSPAlgorithms;
32  import org.bouncycastle.tsp.TimeStampRequest;
33  import org.bouncycastle.tsp.TimeStampRequestGenerator;
34  import org.bouncycastle.tsp.TimeStampResponse;
35  import org.bouncycastle.tsp.TimeStampToken;
36  import org.bouncycastle.tsp.TimeStampTokenGenerator;
37  import org.eparapher.core.crypto.EPKeystoreManager;
38  
39  /*
40   * http://threebit.net/mail-archive/itext-questions/msg04989.html
41   * http://www.berthou.com/fr/2008/01/25/un-timestamp-pour-signer-un-pdf/
42   * http://www.karlverger.com/developpement/signature-electronique-horodatage-bouncycastle-2-54
43   */
44  public class TimeStampManager {
45  
46  	private static Logger log = Logger.getLogger(TimeStampManager.class);
47  	
48  	private static TimeStampManager instance = null;
49  	
50  	public static TimeStampManager getIstance() {
51  		if (instance==null)
52  			instance = new TimeStampManager();
53  		return instance;
54  	}
55  	
56  	private TimeStampManager() {
57  		
58  	}
59  	/**
60  	* Modyfy PKCS#7 data by adding timestamp
61  	*
62  	* (at) param signedData
63  	* (at) throws Exception
64  	*/
65  	private static CMSSignedData addTimestamp(CMSSignedData signedData) throws Exception {
66  		
67  		Collection ss = signedData.getSignerInfos().getSigners();
68  		SignerInformation si = (SignerInformation) ss.iterator().next();
69  		TimeStampToken tok = getTimeStampToken(1);
70  
71  		ASN1InputStream asn1InputStream = new ASN1InputStream (tok.getEncoded());
72  		DERObject tstDER = asn1InputStream.readObject();
73  		DERSet ds = new DERSet(tstDER);
74  		Attribute a = new Attribute(new DERObjectIdentifier("r"), ds);
75  		DEREncodableVector dv = new DEREncodableVector();
76  		dv.add(a);
77  		AttributeTable at = new AttributeTable(dv);
78  		si = SignerInformation.replaceUnsignedAttributes(si, at);
79  		ss.clear();
80  		ss.add(si);
81  		SignerInformationStore sis = new SignerInformationStore(ss);
82  		signedData = CMSSignedData.replaceSigners(signedData, sis);
83  		return signedData;
84  	}
85  
86  	private static TimeStampToken getTimeStampToken(int TSA) throws Exception {
87  
88  		PostMethod post = null;
89  		switch (TSA) {
90  		case 1:
91  			post = new PostMethod("http://www.edelweb.fr/cgi-bin/service-tsp");
92  			break;
93  		case 2:
94  			post = new PostMethod("http://tsp.iaik.at/tsp/TspRequest");
95  			break;
96  		case 3:
97  			post = new PostMethod("http://ns.szikszi.hu:8080/tsa");
98  			break;
99  		case 4:
100 			post = new PostMethod("http://time.certum.pl/");
101 			break;
102 		}
103 
104 		TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator();
105 		//request TSA to return certificate
106 		reqGen.setCertReq (false);
107 		//make a TSP request this is a dummy sha1 hash (20 zero bytes) and nonce=100
108 		TimeStampRequest request =
109 			reqGen.generate(TSPAlgorithms.SHA1,
110 					new byte[20], BigInteger.valueOf(100));
111 
112 		byte[] enc_req = request.getEncoded();
113 		ByteArrayInputStream bais = new ByteArrayInputStream(enc_req);
114 		post.setRequestBody(bais);
115 		post.setRequestContentLength (enc_req.length);
116 		post.setRequestHeader("Content-type","application/timestamp-query");
117 
118 		HttpClient http_client = new HttpClient();
119 		http_client.executeMethod(post);
120 		InputStream in = post.getResponseBodyAsStream();
121 
122 
123 		//read TSP response
124 		TimeStampResponse resp = new TimeStampResponse (in);
125 		resp.validate (request);
126 		log.info("Timestamp validated");
127 
128 		TimeStampToken  tsToken = resp.getTimeStampToken();
129 		SignerId signer_id = tsToken.getSID();
130 
131 
132 		BigInteger cert_serial_number = signer_id.getSerialNumber();
133 
134 
135 		log.info("Signer ID serial "+signer_id.getSerialNumber());
136 		log.info("Signer ID issuer "+signer_id.getIssuerAsString());
137 
138 		CertStore cs = tsToken.getCertificatesAndCRLs ("Collection", "BC");
139 
140 
141 		Collection certs = cs.getCertificates (null);
142 
143 
144 		Iterator iter = certs.iterator();
145 		X509Certificate certificate = null;
146 		while (iter.hasNext()) {
147 			X509Certificate cert = (X509Certificate)iter.next();
148 
149 
150 			if (cert_serial_number != null) {
151 				if (cert.getSerialNumber().equals (cert_serial_number)) {
152 					log.info("using certificate with serial: "+cert.getSerialNumber());
153 					certificate = cert;
154 				}
155 			} else {
156 				if (certificate == null) {
157 					certificate = cert;
158 				}
159 			}
160 			log.info("Certificate subject dn "+cert.getSubjectDN());
161 			log.info("Certificate serial "+cert.getSerialNumber());
162 		}
163 		tsToken.validate(certificate, "BC");
164 		log.info("TS info "+tsToken.getTimeStampInfo().getGenTime());
165 		log.info("TS info "+tsToken.getTimeStampInfo());
166 		log.info("TS info "+tsToken.getTimeStampInfo().getAccuracy());
167 		log.info("TS info "+tsToken.getTimeStampInfo().getNonce());
168 		return tsToken;
169 	}
170     private final static  String KEYSTORE_PASSWORD = "poipoi";
171     private final static  String CERTIFICAT_NAME = "keypairTest";
172     private final static  String CERTIFICAT_PASSWORD = "poipoi";
173     private final static  String TSA_POLICY_ID = "0.0";
174 
175     /**
176      * Création d'un jeton d'horodatage via la date du systeme
177      * pour nos test c'est tout a fait valable nous avons bien un jeton
178      * conforme à la norme si ce n'est que la date n'est pas probante.
179      * et accessoirement nous utilison aussi un certificat autosigné
180      * pour obtenir un jeton ayant valeur légale vous devez obtenir le temps
181      * par un serveur NTP et utiliser une pair de clef fournie aupres d"une PKI
182      * @param empreinte
183      * @param idJeton
184      * @return
185      * @throws java.lang.Exception
186      */
187     public static byte[] getTimestamp(byte[] empreinte, String idJeton) throws Exception {
188         try {
189         	KeyStore ks = EPKeystoreManager.getInstance().getUserkeystore().getKeystore();
190         	
191             // recup keystore, certifs et clefs
192             X509Certificate cert = (X509Certificate) ks.getCertificate(CERTIFICAT_NAME);
193             PrivateKey pk = (PrivateKey) ks.getKey(CERTIFICAT_NAME, CERTIFICAT_PASSWORD.toCharArray());
194             ArrayList certList = new ArrayList();
195             certList.add(cert);
196             CertStore certs = CertStore.getInstance("Collection", new CollectionCertStoreParameters(certList), "BC");
197 
198             String algorithme;
199             algorithme = TSPAlgorithms.SHA1;
200             TimeStampTokenGenerator tokenGen = new TimeStampTokenGenerator(pk, cert, algorithme, TSA_POLICY_ID);
201             tokenGen.setCertificatesAndCRLs(certs);
202 
203             TimeStampRequestGenerator gen = new TimeStampRequestGenerator();
204             gen.setCertReq(true);
205 
206             TimeStampRequest req = gen.generate(algorithme, empreinte, new BigInteger(80, SecureRandom.getInstance("SHA1PRNG")));
207             TimeStampToken token = tokenGen.generate(req, new BigInteger(idJeton), new Date(), "BC");
208             return token.getEncoded();
209         } catch (Exception e) {
210             throw new Exception("Internal error while generating timestamp", e);
211         }
212     }
213 }