View Javadoc

1   /**
2    * LICENCIA LGPL:
3    * 
4    * Esta librería es Software Libre; Usted puede redistribuirla y/o modificarla
5    * bajo los términos de la GNU Lesser General Public License (LGPL) tal y como 
6    * ha sido publicada por la Free Software Foundation; o bien la versión 2.1 de 
7    * la Licencia, o (a su elección) cualquier versión posterior.
8    * 
9    * Esta librería se distribuye con la esperanza de que sea útil, pero SIN 
10   * NINGUNA GARANTÍA; tampoco las implícitas garantías de MERCANTILIDAD o 
11   * ADECUACIÓN A UN PROPÓSITO PARTICULAR. Consulte la GNU Lesser General Public 
12   * License (LGPL) para más detalles
13   * 
14   * Usted debe recibir una copia de la GNU Lesser General Public License (LGPL) 
15   * junto con esta librería; si no es así, escriba a la Free Software Foundation 
16   * Inc. 51 Franklin Street, 5º Piso, Boston, MA 02110-1301, USA o consulte
17   * <http://www.gnu.org/licenses/>.
18   *
19   * Copyright 2011 Agencia de Tecnología y Certificación Electrónica
20   */
21  package es.accv.arangi.base.certificate.validation;
22  
23  import java.io.BufferedOutputStream;
24  import java.io.DataInputStream;
25  import java.io.DataOutputStream;
26  import java.io.File;
27  import java.io.FileInputStream;
28  import java.io.FileNotFoundException;
29  import java.io.IOException;
30  import java.net.HttpURLConnection;
31  import java.net.URL;
32  import java.security.KeyStore;
33  import java.security.KeyStoreException;
34  import java.security.NoSuchAlgorithmException;
35  import java.security.PrivateKey;
36  import java.security.cert.CertificateException;
37  import java.security.cert.X509Certificate;
38  import java.util.Arrays;
39  import java.util.Date;
40  
41  import org.apache.log4j.Logger;
42  import org.bouncycastle.asn1.ASN1Integer;
43  import org.bouncycastle.asn1.ASN1OctetString;
44  import org.bouncycastle.asn1.DEROctetString;
45  import org.bouncycastle.asn1.ocsp.CertID;
46  import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
47  import org.bouncycastle.asn1.x509.GeneralName;
48  import org.bouncycastle.cert.X509CertificateHolder;
49  import org.bouncycastle.cert.ocsp.CertificateID;
50  import org.bouncycastle.cert.ocsp.OCSPException;
51  import org.bouncycastle.cert.ocsp.OCSPReq;
52  import org.bouncycastle.cert.ocsp.OCSPReqBuilder;
53  import org.bouncycastle.cert.ocsp.OCSPResp;
54  import org.bouncycastle.cert.ocsp.OCSPRespBuilder;
55  import org.bouncycastle.operator.ContentSigner;
56  import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
57  import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
58  
59  import es.accv.arangi.base.ArangiObject;
60  import es.accv.arangi.base.algorithm.HashingAlgorithm;
61  import es.accv.arangi.base.certificate.Certificate;
62  import es.accv.arangi.base.document.ByteArrayDocument;
63  import es.accv.arangi.base.exception.certificate.NormalizeCertificateException;
64  import es.accv.arangi.base.exception.certificate.validation.MalformedOCSPResponseException;
65  import es.accv.arangi.base.exception.certificate.validation.OCSPRequestGenerationException;
66  import es.accv.arangi.base.exception.certificate.validation.OCSPServerConnectionException;
67  import es.accv.arangi.base.exception.certificate.validation.OCSPValidateException;
68  import es.accv.arangi.base.exception.device.OpeningDeviceException;
69  import es.accv.arangi.base.exception.document.HashingException;
70  import es.accv.arangi.base.util.Util;
71  import es.accv.arangi.base.util.validation.ValidationResult;
72  
73  /**
74   * Clase que representa un cliente OCSP. Los formatos de las llamadas al OCSP y de
75   * sus respuestas siguen el estándar definido en la <a href="http://www.ietf.org/rfc/rfc2560.txt" target="rfc">RFC-2560</a><br><br>
76   * 
77   * Para validar un certificado:<br><br>
78   * <code>
79   *  CAList caList = new CAList (new File ("/listCA"));<br>
80   *  URL url = new URL ("http://server/ocsp");<br>
81   * 	OCSPClient ocsp = new OCSPClient (url, caList);<br><br>
82   * 
83   * 	Certificate certificate = new Certificate (new File ("c:/certificates/myCertificate.cer"));<br>
84   * 	Certificate issuer = new Certificate (new File ("c:/certificates/myCertificateIssuer.cer"));<br><br>
85   * 
86   * 	int result = ocsp.validate (certificate, issuer);
87   * </code>
88   * 
89   * @author <a href="mailto:jgutierrez@accv.es">José M Gutiérrez</a>
90   */
91  public class OCSPClient extends ArangiObject {
92  
93  	/*
94  	 * Class logger
95  	 */
96  	static Logger logger = Logger.getLogger(OCSPClient.class);
97  	
98  	/*
99  	 * OCSP's URL
100 	 */
101 	URL urlOCSP;
102 	
103 	/*
104 	 * Name that identifies the requestor in the OCSP (normally has null value)
105 	 */
106 	String requestorName;
107 	
108 	/*
109 	 * Keystore to sign requests
110 	 */
111 	KeyStore keyStore;
112 	
113 	/*
114 	 * Alias name associated with a private key inside the keystore. Private key is
115 	 * used to sign the OCSP request
116 	 */
117 	String alias;
118 	
119 	/*
120 	 * Private key password
121 	 */
122 	String aliasPassword;
123 	
124 	/**
125 	 * Constructor con todos los parámetros posibles para realizar la llamada. Normalmente
126 	 * no es necesario crear las llamadas firmadas o con requestor name, por lo que sólo
127 	 * se debe usar este constructor para algún OCSP especial.
128 	 * 
129 	 * @param urlOCSP URL al OCSP
130 	 * @param requestorName Nombre que identifica al llamador en el OCSP
131 	 * @param keystoreFile Fichero keystore
132 	 * @param keystoreType Tipo de keystore (JKS o PKCS12)
133 	 * @param keystorePassword Contraseña del keystore
134 	 * @param alias Alias donde se encuentra la clave privada con la que firmar las
135 	 * 	llamadas OCSP
136 	 * @param aliasPassword Contraseña de la clave privada
137 	 * @throws OpeningDeviceException No se puede abrir el keystore o el alias no existe
138 	 */
139 	public OCSPClient(URL urlOCSP, String requestorName, File keystoreFile, 
140 			String keystoreType, String keystorePassword, String alias, String aliasPassword) throws OpeningDeviceException {
141 		
142 		//-- Load keystore
143 		try {
144 			keyStore = KeyStore.getInstance(keystoreType, CRYPTOGRAPHIC_PROVIDER);
145 		} catch (KeyStoreException e) {
146 			logger.info("[OCSPClient]::Cannot instantiate a keystore with type '" + keystoreType + "'", e);
147 			throw new OpeningDeviceException ("Cannot instantiate a keystore with type '" + keystoreType + "'", e);
148 		} 
149 		FileInputStream fis = null;
150 		try {
151 			fis = new FileInputStream (keystoreFile);
152 			keyStore.load(fis, keystorePassword.toCharArray());
153 		} catch (FileNotFoundException e) {
154 			logger.error("[OCSPClient]::File not found (" + keystoreFile + ")", e);
155 			throw new OpeningDeviceException ("File not found (" + keystoreFile + ")", e);
156 		} catch (NoSuchAlgorithmException e) {
157 			logger.info("[OCSPClient]::The algorithm used to check the integrity of the keystore cannot be found", e);
158 			throw new OpeningDeviceException ("The algorithm used to check the integrity of the keystore cannot be found", e);
159 		} catch (CertificateException e) {
160 			logger.info("[OCSPClient]::Any of the certificates in the keystore could not be loaded", e);
161 			throw new OpeningDeviceException ("Any of the certificates in the keystore could not be loaded", e);
162 		} catch (IOException e) {
163 			logger.info("[OCSPClient]::there is an I/O or format problem with the keystore data", e);
164 			throw new OpeningDeviceException ("there is an I/O or format problem with the keystore data", e);
165 		} finally {
166 			if (fis != null) {
167 				try {
168 					fis.close();
169 				} catch (IOException e) {
170 				}
171 			}
172 		}
173 		
174 		//-- Check if alias exists
175 		try {
176 			if (!keyStore.containsAlias(alias)) {
177 				logger.info("[OCSPClient]::The alias '" + alias + "' is not present in the keystore");
178 				throw new OpeningDeviceException ("The alias '" + alias + "' is not present in the keystore");
179 			}
180 		} catch (KeyStoreException e) {
181 			logger.info("[OCSPClient]::The keystore has not been initialized (loaded)", e);
182 			throw new OpeningDeviceException ("The keystore has not been initialized (loaded)", e);
183 		}
184 		
185 		//-- Load the rest of parameters
186 		this.urlOCSP = urlOCSP;
187 		this.requestorName = requestorName;
188 		this.alias = alias;
189 		this.aliasPassword = aliasPassword;
190 		
191 	}
192 	
193 	/**
194 	 * Constructor con requestorName.
195 	 * 
196 	 * @param urlOCSP URL al OCSP
197 	 * @param requestorName Nombre que identifica al llamador en el OCSP
198 	 */
199 	public OCSPClient(URL urlOCSP, String requestorName) {
200 		
201 		this.urlOCSP = urlOCSP;
202 		this.requestorName = requestorName;
203 		
204 	}
205 	
206 	/**
207 	 * Constructor simple: es el caso más habitual
208 	 * 
209 	 * @param urlOCSP URL al OCSP
210 	 */
211 	public OCSPClient(URL urlOCSP) {
212 		this (urlOCSP, null);
213 	}
214 	
215 	/**
216 	 * Valida el certificado llamando al OCSP.
217 	 * 
218 	 * @param certificate Certificado a validar
219 	 * @param issuerCertificate Certificado emisor
220 	 * @return int Resultado de la validación
221 	 * @throws OCSPRequestGenerationException Errores generando la petición OCSP, probablemente
222 	 * 	debido a los parámetros pasados a éste método
223 	 * @throws OCSPServerConnectionException Errores en la conexión y respuesta del servidor OCSP
224 	 * @throws MalformedOCSPResponseException La respuesta del servidor OCSP no es una respuesta
225 	 * 	OCSP bien formada
226 	 * @throws OCSPValidateException la respuesta no es válida (mal firmada o caducada)
227 	 */
228    	public int validate (Certificate certificate, Certificate issuerCertificate) throws OCSPServerConnectionException, MalformedOCSPResponseException, OCSPRequestGenerationException, OCSPValidateException {
229    		return validate(certificate, issuerCertificate, new Date());
230    	}
231    		
232 	/**
233 	 * Valida el certificado llamando al OCSP.<br/><br/>
234 	 * 
235 	 * NOTA: Para que el método funcione es necesario que el certificado disponga de extensión 
236 	 * 	Authority Key Identifier. De acuerdo al punto 4.2.1.1 de la RFC-3280 este campo es
237 	 * 	obligatorio salvo para certificados autofirmados, pero es posible encontrar certificados
238 	 * 	antiguos o no estandarizados que no dispongan de la extensión.
239 	 * 
240 	 * @param certificate Certificado a validar
241 	 * @return int Resultado de la validación
242 	 * @throws OCSPRequestGenerationException Errores generando la petición OCSP, probablemente
243 	 * 	debido a los parámetros pasados a éste método
244 	 * @throws OCSPServerConnectionException Errores en la conexión y respuesta del servidor OCSP
245 	 * @throws MalformedOCSPResponseException La respuesta del servidor OCSP no es una respuesta
246 	 * 	OCSP bien formada
247 	 * @throws OCSPValidateException la respuesta no es válida (mal firmada o caducada)
248 	 */
249    	public int validate (Certificate certificate) throws OCSPServerConnectionException, MalformedOCSPResponseException, OCSPRequestGenerationException, OCSPValidateException {
250    		return validate(certificate, new Date());
251    	}
252    		
253 	/**
254 	 * Valida el certificado llamando al OCSP.<br><br>
255 	 * 
256 	 * NOTA: la mayoría de Autoridades de Certificación eliminan la información de revocación
257 	 * de los certificados caducados de sus CRLs. En estos casos la validación histórica no
258 	 * es posible y Arangi devolverá que el certificado era válido, ya que tanto la CRL como
259 	 * el OCSP devuelven este resultado. La única forma de realizar validación histórica sería 
260 	 * dentro de un proceso de firma longeva.
261 	 * 
262 	 * @param certificate Certificado a validar
263 	 * @param issuerCertificate Certificado emisor
264 	 * @param validationDate Fecha en que se realizará la validación
265 	 * @return int Resultado de la validación
266 	 * @throws OCSPRequestGenerationException Errores generando la petición OCSP, probablemente
267 	 * 	debido a los parámetros pasados a éste método
268 	 * @throws OCSPServerConnectionException Errores en la conexión y respuesta del servidor OCSP
269 	 * @throws MalformedOCSPResponseException La respuesta del servidor OCSP no es una respuesta
270 	 * 	OCSP bien formada
271 	 * @throws OCSPValidateException la respuesta no es válida (mal firmada o caducada)
272 	 */
273    	public int validate (Certificate certificate, Certificate issuerCertificate, Date validationDate) throws OCSPServerConnectionException, MalformedOCSPResponseException, OCSPRequestGenerationException, OCSPValidateException {
274    		return validate (new Certificate[] { certificate }, new Certificate [] { issuerCertificate }, validationDate) [0];
275    	}
276    	
277 	/**
278 	 * Valida el certificado llamando al OCSP.<br><br>
279 	 * 
280 	 * NOTA: la mayoría de Autoridades de Certificación eliminan la información de revocación
281 	 * de los certificados caducados de sus CRLs. En estos casos la validación histórica no
282 	 * es posible y Arangi devolverá que el certificado era válido, ya que tanto la CRL como
283 	 * el OCSP devuelven este resultado. La única forma de realizar validación histórica sería 
284 	 * dentro de un proceso de firma longeva.<br/><br/>
285 	 * 
286 	 * NOTA: Para que el método funcione es necesario que el certificado disponga de extensión 
287 	 * 	Authority Key Identifier. De acuerdo al punto 4.2.1.1 de la RFC-3280 este campo es
288 	 * 	obligatorio salvo para certificados autofirmados, pero es posible encontrar certificados
289 	 * 	antiguos o no estandarizados que no dispongan de la extensión.
290 	 * 
291 	 * @param certificate Certificado a validar
292 	 * @param validationDate Fecha en que se realizará la validación
293 	 * @return int Resultado de la validación
294 	 * @throws OCSPRequestGenerationException Errores generando la petición OCSP, probablemente
295 	 * 	debido a los parámetros pasados a éste método
296 	 * @throws OCSPServerConnectionException Errores en la conexión y respuesta del servidor OCSP
297 	 * @throws MalformedOCSPResponseException La respuesta del servidor OCSP no es una respuesta
298 	 * 	OCSP bien formada
299 	 * @throws OCSPValidateException la respuesta no es válida (mal firmada o caducada)
300 	 */
301    	public int validate (Certificate certificate, Date validationDate) throws OCSPServerConnectionException, MalformedOCSPResponseException, OCSPRequestGenerationException, OCSPValidateException {
302    		return validate (new Certificate[] { certificate }, validationDate) [0];
303    	}
304    	
305 	/**
306 	 * Valida los certificados llamando al OCSP.
307 	 * 
308 	 * @param certificates Certificados a validar
309 	 * @param issuerCertificates Certificados emisores
310 	 * @return int Resultado de la validación
311 	 * @throws OCSPRequestGenerationException Errores generando la petición OCSP, probablemente
312 	 * 	debido a los parámetros pasados a éste método
313 	 * @throws OCSPServerConnectionException Errores en la conexión y respuesta del servidor OCSP
314 	 * @throws MalformedOCSPResponseException La respuesta del servidor OCSP no es una respuesta
315 	 * 	OCSP bien formada
316 	 * @throws OCSPValidateException la respuesta no es válida (mal firmada o caducada)
317 	 * @throws NormalizeCertificateException No es posible normalizar alguno de los certificados 
318 	 * 	de acuerdo al proveedor criptográfico de Arangí
319 	 */
320    	public int[] validate (X509Certificate[] certificates, X509Certificate[] issuerCertificates) throws OCSPServerConnectionException, MalformedOCSPResponseException, OCSPRequestGenerationException, OCSPValidateException, NormalizeCertificateException {
321    		return validate (certificates, issuerCertificates, new Date());
322    	}
323    	
324 	/**
325 	 * Valida los certificados llamando al OCSP.<br/><br/>
326 	 * 
327 	 * NOTA: Para que el método funcione es necesario que los certificados dispongan de extensión 
328 	 * 	Authority Key Identifier. De acuerdo al punto 4.2.1.1 de la RFC-3280 este campo es
329 	 * 	obligatorio salvo para certificados autofirmados, pero es posible encontrar certificados
330 	 * 	antiguos o no estandarizados que no dispongan de la extensión.
331 	 * 
332 	 * @param certificates Certificados a validar
333 	 * @return int Resultado de la validación
334 	 * @throws OCSPRequestGenerationException Errores generando la petición OCSP, probablemente
335 	 * 	debido a los parámetros pasados a éste método
336 	 * @throws OCSPServerConnectionException Errores en la conexión y respuesta del servidor OCSP
337 	 * @throws MalformedOCSPResponseException La respuesta del servidor OCSP no es una respuesta
338 	 * 	OCSP bien formada
339 	 * @throws OCSPValidateException la respuesta no es válida (mal firmada o caducada)
340 	 * @throws NormalizeCertificateException No es posible normalizar alguno de los certificados 
341 	 * 	de acuerdo al proveedor criptográfico de Arangí
342 	 */
343    	public int[] validate (X509Certificate[] certificates) throws OCSPServerConnectionException, MalformedOCSPResponseException, OCSPRequestGenerationException, OCSPValidateException, NormalizeCertificateException {
344    		return validate (certificates, new Date());
345    	}
346    	
347 	/**
348 	 * Valida los certificados llamando al OCSP.
349 	 * 
350 	 * NOTA: la mayoría de Autoridades de Certificación eliminan la información de revocación
351 	 * de los certificados caducados de sus CRLs. En estos casos la validación histórica no
352 	 * es posible y Arangi devolverá que el certificado era válido, ya que tanto la CRL como
353 	 * el OCSP devuelven este resultado. La única forma de realizar validación histórica sería 
354 	 * dentro de un proceso de firma longeva.
355 	 * 
356 	 * @param certificates Certificados a validar
357 	 * @param issuerCertificates Certificados emisores
358 	 * @param validationDate Fecha en que se realizará la validación
359 	 * @return int Resultado de la validación
360 	 * @throws OCSPRequestGenerationException Errores generando la petición OCSP, probablemente
361 	 * 	debido a los parámetros pasados a éste método
362 	 * @throws OCSPServerConnectionException Errores en la conexión y respuesta del servidor OCSP
363 	 * @throws MalformedOCSPResponseException La respuesta del servidor OCSP no es una respuesta
364 	 * 	OCSP bien formada
365 	 * @throws OCSPValidateException la respuesta no es válida (mal firmada o caducada)
366 	 * @throws NormalizeCertificateException No es posible normalizar alguno de los certificados 
367 	 * 	de acuerdo al proveedor criptográfico de Arangí
368 	 */
369    	public int[] validate (X509Certificate[] certificates, X509Certificate[] issuerCertificates, Date validationDate) throws OCSPServerConnectionException, MalformedOCSPResponseException, OCSPRequestGenerationException, OCSPValidateException, NormalizeCertificateException {
370    		Certificate[] arangiCertificates = new Certificate [certificates.length];
371    		Certificate[] arangiIssuers = new Certificate [certificates.length];
372    		for (int i = 0; i < certificates.length; i++) {
373    			arangiCertificates[i] = new Certificate (certificates[i]);
374    			arangiIssuers[i] = new Certificate (issuerCertificates[i]);
375 		}
376    		return validate (arangiCertificates, arangiIssuers, validationDate);
377    	}
378    		
379 	/**
380 	 * Valida los certificados llamando al OCSP.
381 	 * 
382 	 * NOTA: la mayoría de Autoridades de Certificación eliminan la información de revocación
383 	 * de los certificados caducados de sus CRLs. En estos casos la validación histórica no
384 	 * es posible y Arangi devolverá que el certificado era válido, ya que tanto la CRL como
385 	 * el OCSP devuelven este resultado. La única forma de realizar validación histórica sería 
386 	 * dentro de un proceso de firma longeva.<br/><br/>
387 	 * 
388 	 * NOTA: Para que el método funcione es necesario que los certificados dispongan de extensión 
389 	 * 	Authority Key Identifier. De acuerdo al punto 4.2.1.1 de la RFC-3280 este campo es
390 	 * 	obligatorio salvo para certificados autofirmados, pero es posible encontrar certificados
391 	 * 	antiguos o no estandarizados que no dispongan de la extensión.
392 	 * 
393 	 * @param certificates Certificados a validar
394 	 * @param validationDate Fecha en que se realizará la validación
395 	 * @return int Resultado de la validación
396 	 * @throws OCSPRequestGenerationException Errores generando la petición OCSP, probablemente
397 	 * 	debido a los parámetros pasados a éste método
398 	 * @throws OCSPServerConnectionException Errores en la conexión y respuesta del servidor OCSP
399 	 * @throws MalformedOCSPResponseException La respuesta del servidor OCSP no es una respuesta
400 	 * 	OCSP bien formada
401 	 * @throws OCSPValidateException la respuesta no es válida (mal firmada o caducada)
402 	 * @throws NormalizeCertificateException No es posible normalizar alguno de los certificados 
403 	 * 	de acuerdo al proveedor criptográfico de Arangí
404 	 */
405    	public int[] validate (X509Certificate[] certificates, Date validationDate) throws OCSPServerConnectionException, MalformedOCSPResponseException, OCSPRequestGenerationException, OCSPValidateException, NormalizeCertificateException {
406    		Certificate[] arangiCertificates = new Certificate [certificates.length];
407    		for (int i = 0; i < certificates.length; i++) {
408    			arangiCertificates[i] = new Certificate (certificates[i]);
409 		}
410    		return validate (arangiCertificates, validationDate);
411    	}
412    		
413 	/**
414 	 * Valida los certificados llamando al OCSP.<br><br>
415 	 * 
416 	 * @param certificates Certificados a validar
417 	 * @param issuerCertificates Certificados emisores
418 	 * @return int Resultado de la validación
419 	 * @throws OCSPRequestGenerationException Errores generando la petición OCSP, probablemente
420 	 * 	debido a los parámetros pasados a éste método
421 	 * @throws OCSPServerConnectionException Errores en la conexión y respuesta del servidor OCSP
422 	 * @throws MalformedOCSPResponseException La respuesta del servidor OCSP no es una respuesta
423 	 * 	OCSP bien formada
424 	 * @throws OCSPValidateException la respuesta no es válida (mal firmada o caducada)
425 	 */
426    	public int[] validate (Certificate[] certificates, Certificate[] issuerCertificates) throws OCSPServerConnectionException, MalformedOCSPResponseException, OCSPRequestGenerationException, OCSPValidateException {
427    		return validate (certificates, issuerCertificates, new Date());
428    	}
429    	
430 	/**
431 	 * Valida los certificados llamando al OCSP.<br/><br/>
432 	 * 
433 	 * NOTA: Para que el método funcione es necesario que el certificado disponga de extensión 
434 	 * 	Authority Key Identifier. De acuerdo al punto 4.2.1.1 de la RFC-3280 este campo es
435 	 * 	obligatorio salvo para certificados autofirmados, pero es posible encontrar certificados
436 	 * 	antiguos o no estandarizados que no dispongan de la extensión.<br><br>
437 	 * 
438 	 * @param certificates Certificados a validar
439 	 * @return int Resultado de la validación
440 	 * @throws OCSPRequestGenerationException Errores generando la petición OCSP, probablemente
441 	 * 	debido a los parámetros pasados a éste método
442 	 * @throws OCSPServerConnectionException Errores en la conexión y respuesta del servidor OCSP
443 	 * @throws MalformedOCSPResponseException La respuesta del servidor OCSP no es una respuesta
444 	 * 	OCSP bien formada
445 	 * @throws OCSPValidateException la respuesta no es válida (mal firmada o caducada)
446 	 */
447    	public int[] validate (Certificate[] certificates) throws OCSPServerConnectionException, MalformedOCSPResponseException, OCSPRequestGenerationException, OCSPValidateException {
448    		return validate (certificates, new Date());
449    	}
450    	
451 	/**
452 	 * Valida los certificados llamando al OCSP.<br><br>
453 	 * 
454 	 * NOTA: la mayoría de Autoridades de Certificación eliminan la información de revocación
455 	 * de los certificados caducados de sus CRLs. En estos casos la validación histórica no
456 	 * es posible y Arangi devolverá que el certificado era válido, ya que tanto la CRL como
457 	 * el OCSP devuelven este resultado. La única forma de realizar validación histórica sería 
458 	 * dentro de un proceso de firma longeva.
459 	 * 
460 	 * @param certificates Certificados a validar
461 	 * @param issuerCertificates Certificados emisores
462 	 * @param validationDate Fecha en que se realizará la validación
463 	 * @return int Resultado de la validación
464 	 * @throws OCSPRequestGenerationException Errores generando la petición OCSP, probablemente
465 	 * 	debido a los parámetros pasados a éste método
466 	 * @throws OCSPServerConnectionException Errores en la conexión y respuesta del servidor OCSP
467 	 * @throws MalformedOCSPResponseException La respuesta del servidor OCSP no es una respuesta
468 	 * 	OCSP bien formada
469 	 * @throws OCSPValidateException la respuesta no es válida (mal firmada o caducada)
470 	 */
471    	public int[] validate (Certificate[] certificates, Certificate[] issuerCertificates, Date validationDate) throws OCSPServerConnectionException, MalformedOCSPResponseException, OCSPRequestGenerationException, OCSPValidateException {
472    		logger.debug("[OCSPClient.validate] :: Start :: " + Arrays.asList(new Object[] { certificates, validationDate }));
473    		
474    		//-- Obtener la respuesta OCSP
475    		OCSPResponse oscpResponse = getOCSPResponse(certificates, issuerCertificates);
476    		
477      	if (!oscpResponse.isSignatureValid ()) {
478    			logger.info ("[OCSPClient.validate] :: La firma de la respuesta OCSP no es correcta");
479    			throw new OCSPValidateException ("La firma de la respuesta OCSP no es correcta");
480      	}
481 		
482      	//-- Objeto resultados
483      	int [] result = new int [certificates.length];
484      	
485      	//-- Obtener resultados
486      	CertificateOCSPResponse[] singleResponses = oscpResponse.getSingleResponses();
487      	for (int i = 0; i < singleResponses.length; i++) {
488 			if(singleResponses[i] != null) {
489 				
490 				//-- Check validity interval
491 				if (singleResponses[i].getValidityPeriodEnd() != null && singleResponses[i].getValidityPeriodEnd().before(new Date())) {
492 		   			logger.error ("[OCSPClient.validate] :: La respuesta OCSP ha superado su periodo de validez, que acababa el " + Util.dateFormatAccurate.format(singleResponses[i].getValidityPeriodEnd()));
493 		   			throw new OCSPValidateException ("La respuesta OCSP ha superado su periodo de validez, que acababa el " + Util.dateFormatAccurate.format(singleResponses[i].getValidityPeriodEnd()));
494 				}
495 				
496 				//-- Return result
497 		     	if(singleResponses[i].getStatus() != ValidationResult.RESULT_CERTIFICATE_REVOKED){
498 		     		//-- Certificate valid or unknown
499 		     		result [i] = singleResponses[i].getStatus();
500 		     		
501 		     	}else{
502 		     		//-- Certificate is revoked: mirar la fecha de revocación y compararla con la fecha en que se quiere la validación
503 	     			if (singleResponses[i].getRevocationTime().before(validationDate) || singleResponses[i].getRevocationTime().equals(validationDate)) {
504 		     			//-- Certificate revoked
505 	     				result [i] =  ValidationResult.RESULT_CERTIFICATE_REVOKED;
506 	     			} else {
507 			     		//-- Certificate revoked, but revokation is after the validation date
508 	     				result [i] =  ValidationResult.RESULT_VALID;
509 	     			}
510 		     	}			
511 			}
512 			
513 		}
514      	
515      	//-- Devolver resultado
516      	return result;
517    	}
518    	
519 	/**
520 	 * Valida los certificados llamando al OCSP.<br><br>
521 	 * 
522 	 * NOTA: la mayoría de Autoridades de Certificación eliminan la información de revocación
523 	 * de los certificados caducados de sus CRLs. En estos casos la validación histórica no
524 	 * es posible y Arangi devolverá que el certificado era válido, ya que tanto la CRL como
525 	 * el OCSP devuelven este resultado. La única forma de realizar validación histórica sería 
526 	 * dentro de un proceso de firma longeva.<br/><br/>
527 	 * 
528 	 * NOTA: Para que el método funcione es necesario que el certificado disponga de extensión 
529 	 * 	Authority Key Identifier. De acuerdo al punto 4.2.1.1 de la RFC-3280 este campo es
530 	 * 	obligatorio salvo para certificados autofirmados, pero es posible encontrar certificados
531 	 * 	antiguos o no estandarizados que no dispongan de la extensión.
532 	 * 
533 	 * @param certificates Certificados a validar
534 	 * @param validationDate Fecha en que se realizará la validación
535 	 * @return int Resultado de la validación
536 	 * @throws OCSPRequestGenerationException Errores generando la petición OCSP, probablemente
537 	 * 	debido a los parámetros pasados a éste método
538 	 * @throws OCSPServerConnectionException Errores en la conexión y respuesta del servidor OCSP
539 	 * @throws MalformedOCSPResponseException La respuesta del servidor OCSP no es una respuesta
540 	 * 	OCSP bien formada
541 	 * @throws OCSPValidateException la respuesta no es válida (mal firmada o caducada)
542 	 */
543    	public int[] validate (Certificate[] certificates, Date validationDate) throws OCSPServerConnectionException, MalformedOCSPResponseException, OCSPRequestGenerationException, OCSPValidateException {
544    		
545    		logger.debug("[OCSPClient.validate] :: Start :: " + Arrays.asList(new Object[] { certificates, validationDate }));
546    		
547    		//-- Obtener la respuesta OCSP
548    		OCSPResponse oscpResponse = getOCSPResponse(certificates);
549    		
550      	if (!oscpResponse.isSignatureValid ()) {
551    			logger.info ("[OCSPClient.validate] :: La firma de la respuesta OCSP no es correcta");
552    			throw new OCSPValidateException ("La firma de la respuesta OCSP no es correcta");
553      	}
554 		
555      	//-- Objeto resultados
556      	int [] result = new int [certificates.length];
557      	
558      	//-- Obtener resultados
559      	CertificateOCSPResponse[] singleResponses = oscpResponse.getSingleResponses();
560      	for (int i = 0; i < singleResponses.length; i++) {
561 			if(singleResponses[i] != null) {
562 				
563 				//-- Check validity interval
564 				if (singleResponses[i].getValidityPeriodEnd() != null && singleResponses[i].getValidityPeriodEnd().before(new Date())) {
565 		   			logger.error ("[OCSPClient.validate] :: La respuesta OCSP ha superado su periodo de validez, que acababa el " + Util.dateFormatAccurate.format(singleResponses[i].getValidityPeriodEnd()));
566 		   			throw new OCSPValidateException ("La respuesta OCSP ha superado su periodo de validez, que acababa el " + Util.dateFormatAccurate.format(singleResponses[i].getValidityPeriodEnd()));
567 				}
568 				
569 				//-- Return result
570 		     	if(singleResponses[i].getStatus() != ValidationResult.RESULT_CERTIFICATE_REVOKED){
571 		     		//-- Certificate valid or unknown
572 		     		result [i] = singleResponses[i].getStatus();
573 		     		
574 		     	}else{
575 		     		//-- Certificate is revoked: mirar la fecha de revocación y compararla con la fecha en que se quiere la validación
576 	     			if (singleResponses[i].getRevocationTime().before(validationDate) || singleResponses[i].getRevocationTime().equals(validationDate)) {
577 		     			//-- Certificate revoked
578 	     				result [i] =  ValidationResult.RESULT_CERTIFICATE_REVOKED;
579 	     			} else {
580 			     		//-- Certificate revoked, but revokation is after the validation date
581 	     				result [i] =  ValidationResult.RESULT_VALID;
582 	     			}
583 		     	}			
584 			}
585 			
586 		}
587      	
588      	//-- Devolver resultado
589      	return result;
590 	}
591 
592 	/**
593 	 * Obtiene una respuesta del OCSP. En caso de que el OCSP devuelva una respuesta con
594 	 * errores, éstos se transformarán en una excepción OCSPException. <br><br>
595 	 * 
596 	 * Esta respuesta puede ser utilizada dentro del proceso de creación de una firma longeva.
597 	 * 
598 	 * @param certificate Certificado a validar
599 	 * @param issuerCertificate Certificado emisor
600 	 * @return Respuesta del OCSP
601 	 * @throws NormalizeCertificateException Alguno de los certificados no ha podido ser 
602 	 * 	normalizado al proveedor criptográfico de Arangí
603 	 * @throws OCSPRequestGenerationException Errores generando la petición OCSP, probablemente
604 	 * 	debido a los parámetros pasados a éste método
605 	 * @throws OCSPServerConnectionException Errores en la conexión y respuesta del servidor OCSP
606 	 * @throws MalformedOCSPResponseException La respuesta del servidor OCSP no es una respuesta
607 	 * 	OCSP bien formada
608 	 */
609    	public OCSPResponse getOCSPResponse (X509Certificate certificate, X509Certificate issuerCertificate) throws OCSPServerConnectionException, MalformedOCSPResponseException, OCSPRequestGenerationException, NormalizeCertificateException {
610    		return getOCSPResponse(new Certificate (certificate), new Certificate (issuerCertificate));
611    	}
612    		
613 	/**
614 	 * Obtiene una respuesta del OCSP. En caso de que el OCSP devuelva una respuesta con
615 	 * errores, éstos se transformarán en una excepción OCSPException. <br><br>
616 	 * 
617 	 * Esta respuesta puede ser utilizada dentro del proceso de creación de una firma longeva.<br/><br/>
618 	 * 
619 	 * NOTA: Para que el método funcione es necesario que el certificado disponga de extensión 
620 	 * 	Authority Key Identifier. De acuerdo al punto 4.2.1.1 de la RFC-3280 este campo es
621 	 * 	obligatorio salvo para certificados autofirmados, pero es posible encontrar certificados
622 	 * 	antiguos o no estandarizados que no dispongan de la extensión.
623 	 * 
624 	 * @param certificate Certificado a validar
625 	 * @return Respuesta del OCSP
626 	 * @throws NormalizeCertificateException Alguno de los certificados no ha podido ser 
627 	 * 	normalizado al proveedor criptográfico de Arangí
628 	 * @throws OCSPRequestGenerationException Errores generando la petición OCSP, probablemente
629 	 * 	debido a los parámetros pasados a éste método
630 	 * @throws OCSPServerConnectionException Errores en la conexión y respuesta del servidor OCSP
631 	 * @throws MalformedOCSPResponseException La respuesta del servidor OCSP no es una respuesta
632 	 * 	OCSP bien formada
633 	 */
634    	public OCSPResponse getOCSPResponse (X509Certificate certificate) throws OCSPServerConnectionException, MalformedOCSPResponseException, OCSPRequestGenerationException, NormalizeCertificateException {
635    		return getOCSPResponse(new Certificate (certificate));
636    	}
637    		
638 	/**
639 	 * Obtiene una respuesta del OCSP. En caso de que el OCSP devuelva una respuesta con
640 	 * errores, éstos se transformarán en una excepción OCSPException. <br><br>
641 	 * 
642 	 * Esta respuesta puede ser utilizada dentro del proceso de creación de una firma longeva.
643 	 * 
644 	 * @param certificate Certificado a validar
645 	 * @param issuerCertificate Certificado emisor
646 	 * @return Respuesta del OCSP
647 	 * @throws OCSPRequestGenerationException Errores generando la petición OCSP, probablemente
648 	 * 	debido a los parámetros pasados a éste método
649 	 * @throws OCSPServerConnectionException Errores en la conexión y respuesta del servidor OCSP
650 	 * @throws MalformedOCSPResponseException La respuesta del servidor OCSP no es una respuesta
651 	 * 	OCSP bien formada
652 	 */
653    	public OCSPResponse getOCSPResponse (Certificate certificate, Certificate issuerCertificate) throws OCSPServerConnectionException, MalformedOCSPResponseException, OCSPRequestGenerationException {
654    		return getOCSPResponse(new Certificate[] {certificate}, new Certificate [] {issuerCertificate});
655    	}
656    		
657 	/**
658 	 * Obtiene una respuesta del OCSP. En caso de que el OCSP devuelva una respuesta con
659 	 * errores, éstos se transformarán en una excepción OCSPException. <br><br>
660 	 * 
661 	 * Esta respuesta puede ser utilizada dentro del proceso de creación de una firma longeva.
662 	 * 
663 	 * @param certificate Certificado a validar
664 	 * @return Respuesta del OCSP
665 	 * @throws OCSPRequestGenerationException Errores generando la petición OCSP, probablemente
666 	 * 	debido a los parámetros pasados a éste método
667 	 * @throws OCSPServerConnectionException Errores en la conexión y respuesta del servidor OCSP
668 	 * @throws MalformedOCSPResponseException La respuesta del servidor OCSP no es una respuesta
669 	 * 	OCSP bien formada
670 	 */
671    	public OCSPResponse getOCSPResponse (ValidateCertificate certificate) throws OCSPServerConnectionException, MalformedOCSPResponseException, OCSPRequestGenerationException {
672    		return getOCSPResponse(new Certificate[] {certificate}, new Certificate[] {certificate.getIssuerCertificate()});
673    	}
674    		
675 	/**
676 	 * Obtiene una respuesta del OCSP. En caso de que el OCSP devuelva una respuesta con
677 	 * errores, éstos se transformarán en una excepción OCSPException. <br><br>
678 	 * 
679 	 * Esta respuesta puede ser utilizada dentro del proceso de creación de una firma longeva.<br/><br/>
680 	 * 
681 	 * NOTA: Para que el método funcione es necesario que el certificado disponga de extensión 
682 	 * 	Authority Key Identifier. De acuerdo al punto 4.2.1.1 de la RFC-3280 este campo es
683 	 * 	obligatorio salvo para certificados autofirmados, pero es posible encontrar certificados
684 	 * 	antiguos o no estandarizados que no dispongan de la extensión.
685 	 * 
686 	 * @param certificate Certificado a validar
687 	 * @return Respuesta del OCSP
688 	 * @throws OCSPRequestGenerationException Errores generando la petición OCSP, probablemente
689 	 * 	debido a los parámetros pasados a éste método
690 	 * @throws OCSPServerConnectionException Errores en la conexión y respuesta del servidor OCSP
691 	 * @throws MalformedOCSPResponseException La respuesta del servidor OCSP no es una respuesta
692 	 * 	OCSP bien formada
693 	 */
694    	public OCSPResponse getOCSPResponse (Certificate certificate) throws OCSPServerConnectionException, MalformedOCSPResponseException, OCSPRequestGenerationException {
695    		return getOCSPResponse(new Certificate[] {certificate});
696    	}
697    		
698 	/**
699 	 * Obtiene una respuesta del OCSP. En caso de que el OCSP devuelva una respuesta con
700 	 * errores, éstos se transformarán en una excepción OCSPException. <br><br>
701 	 * 
702 	 * Esta respuesta puede ser utilizada dentro del proceso de creación de una firma longeva.
703 	 * 
704 	 * @param certificates Certificados a validar (debe tener el mismo tamaño que issuerCertificates)
705 	 * @param issuerCertificates Certificados emisores (debe tener el mismo tamaño que 
706 	 * 	certificates)
707 	 * @return Respuesta del OCSP
708 	 * @throws OCSPRequestGenerationException Errores generando la petición OCSP, probablemente
709 	 * 	debido a los parámetros pasados a éste método
710 	 * @throws OCSPServerConnectionException Errores en la conexión y respuesta del servidor OCSP
711 	 * @throws MalformedOCSPResponseException La respuesta del servidor OCSP no es una respuesta
712 	 * 	OCSP bien formada
713 	 */
714    	public OCSPResponse getOCSPResponse (Certificate[] certificates, Certificate[] issuerCertificates) throws OCSPServerConnectionException, MalformedOCSPResponseException, OCSPRequestGenerationException {
715    		
716    		logger.debug("[OCSPClient.getOCSPResponse] :: Entrada");
717    		
718   		//-- If certificate is null throw an exception
719    		if (certificates == null || certificates.length == 0) {
720    			logger.info ("[OCSPClient.getOCSPResponse] :: No hay certificados a validar");
721    			throw new OCSPRequestGenerationException ("No hay certificados a validar");
722    		}
723    		
724    		//-- If certificate issuer is null throw an exception
725    		if (issuerCertificates == null || issuerCertificates.length == 0) {
726    			logger.info ("[OCSPClient.getOCSPResponse] :: No hay certificados emisores para realizar la validación");
727    			throw new OCSPRequestGenerationException ("No hay certificados emisores para realizar la validación");
728    		}
729    		
730    		//-- If certificate issuer is null throw an exception
731    		if (certificates.length != issuerCertificates.length) {
732    			logger.info ("[OCSPClient.getOCSPResponse] :: El tamaño de los arrays de certificados y emisores es diferente");
733    			throw new OCSPRequestGenerationException ("El tamaño de los arrays de certificados y emisores es diferente");
734    		}
735    		
736    		//-- Generate the OCSP request
737    		byte[] ocspRequest = generateOCSPRequest(certificates,	issuerCertificates, requestorName, keyStore, alias, aliasPassword);
738    		
739    		//-- Obtener respuesta
740 	    return getOCSPResponse(ocspRequest);
741 	}
742 
743 	/**
744 	 * Obtiene una respuesta del OCSP. En caso de que el OCSP devuelva una respuesta con
745 	 * errores, éstos se transformarán en una excepción OCSPException. <br><br>
746 	 * 
747 	 * Esta respuesta puede ser utilizada dentro del proceso de creación de una firma longeva.<br/><br/>
748 	 * 
749 	 * NOTA: Para que el método funcione es necesario que los certificados dispongan de extensión 
750 	 * 	Authority Key Identifier. De acuerdo al punto 4.2.1.1 de la RFC-3280 este campo es
751 	 * 	obligatorio salvo para certificados autofirmados, pero es posible encontrar certificados
752 	 * 	antiguos o no estandarizados que no dispongan de la extensión.
753 	 * 
754 	 * @param certificates Certificados a validar (debe tener el mismo tamaño que issuerCertificates)
755 	 * @return Respuesta del OCSP
756 	 * @throws OCSPRequestGenerationException Errores generando la petición OCSP, probablemente
757 	 * 	debido a los parámetros pasados a éste método
758 	 * @throws OCSPServerConnectionException Errores en la conexión y respuesta del servidor OCSP
759 	 * @throws MalformedOCSPResponseException La respuesta del servidor OCSP no es una respuesta
760 	 * 	OCSP bien formada
761 	 */
762    	public OCSPResponse getOCSPResponse (Certificate[] certificates) throws OCSPServerConnectionException, MalformedOCSPResponseException, OCSPRequestGenerationException {
763    		
764    		logger.debug("[OCSPClient.getOCSPResponse] :: Entrada");
765    		
766    		//-- If certificate is null throw an exception
767    		if (certificates == null || certificates.length == 0) {
768    			logger.info ("[OCSPClient.getOCSPResponse] :: No hay certificados a validar");
769    			throw new OCSPRequestGenerationException ("No hay certificados a validar");
770    		}
771    		
772    		//-- Generate the OCSP request
773    		byte[] ocspRequest = generateOCSPRequest(certificates, requestorName, keyStore, alias, aliasPassword);
774    		
775    		//-- Obtener respuesta
776 	    return getOCSPResponse(ocspRequest);
777 	}
778 
779 	/**
780 	 * Genera una petición OCSP.
781 	 * 
782 	 * @param certificate Certificado a validar
783 	 * @param issuerCertificate Certificado emisor
784 	 * @return Array de bytes con la petición OCSP
785 	 * @throws Exception Errores durante la generación
786 	 */
787    	public static  byte[] generateOCSPRequest(Certificate certificate, Certificate issuerCertificate) throws Exception{
788    		
789    		return generateOCSPRequest(new Certificate [] { certificate }, new Certificate [] { issuerCertificate });
790    		
791    	}
792    	
793 	/**
794 	 * Genera una petición OCSP.<br/><br/>
795 	 * 
796 	 * NOTA: Para que el método funcione es necesario que el certificado disponga de extensión 
797 	 * 	Authority Key Identifier. De acuerdo al punto 4.2.1.1 de la RFC-3280 este campo es
798 	 * 	obligatorio salvo para certificados autofirmados, pero es posible encontrar certificados
799 	 * 	antiguos o no estandarizados que no dispongan de la extensión.
800 	 * 
801 	 * @param certificate Certificado a validar
802 	 * @return Array de bytes con la petición OCSP
803 	 * @throws Exception Errores durante la generación
804 	 */
805    	public static  byte[] generateOCSPRequest(Certificate certificate) throws Exception{
806    		
807    		return generateOCSPRequest(new Certificate [] { certificate });
808    		
809    	}
810    	
811    	/**
812 	 * Genera una petición OCSP múltiple: se validarán varios certificados al mismo tiempo.
813 	 * 
814 	 * @param certificates Certificados a validar
815 	 * @param issuerCertificates Emisores de los certificados
816 	 * @return Array de bytes con la petición OCSP
817 	 * @throws Exception Errores durante la generación
818 	 */
819    	public static  byte[] generateOCSPRequest(Certificate [] certificates, Certificate [] issuerCertificates) throws Exception{
820    		
821    		return OCSPClient.generateOCSPRequest(certificates, issuerCertificates, null, null, null, null);
822    		
823    	}
824    	
825    	/**
826 	 * Genera una petición OCSP múltiple: se validarán varios certificados al mismo tiempo.<br/><br/>
827 	 * 
828 	 * NOTA: Para que el método funcione es necesario que los certificados dispongan de extensión 
829 	 * 	Authority Key Identifier. De acuerdo al punto 4.2.1.1 de la RFC-3280 este campo es
830 	 * 	obligatorio salvo para certificados autofirmados, pero es posible encontrar certificados
831 	 * 	antiguos o no estandarizados que no dispongan de la extensión.
832 	 * 
833 	 * @param certificates Certificados a validar
834 	 * @return Array de bytes con la petición OCSP
835 	 * @throws Exception Errores durante la generación
836 	 */
837    	public static  byte[] generateOCSPRequest(Certificate [] certificates) throws Exception{
838    		
839    		return OCSPClient.generateOCSPRequest(certificates, null, null, null, null);
840    		
841    	}
842    	
843    	/**
844 	 * Genera una petición OCSP múltiple: se validarán varios certificados al mismo tiempo.
845 	 * La petición ser firmará.
846    	 * 
847 	 * @param certificates Certificados a validar
848 	 * @param issuerCertificates Emisores de los certificados
849 	 * @param requestorName Nombre que identifica al llamador en el OCSP
850 	 * @param keystore Keystore abierto que contiene la clave privada que firma la petición
851 	 * @param alias Alias del keystore para firmar la petición
852 	 * @param aliasPassword Contraseña de la clave privada
853 	 * @return Array de bytes con la petición OCSP
854    	 * @throws OCSPRequestGenerationException Errores durante la generación
855    	 */
856    	public static  byte[] generateOCSPRequest(Certificate [] certificates, Certificate [] issuerCertificates,
857    			String requestorName, KeyStore keystore, String alias, String aliasPassword) throws OCSPRequestGenerationException{
858 		
859    		//-- Validate parameters
860    		if (certificates == null || certificates.length == 0) {
861    			throw new OCSPRequestGenerationException ("List of certificates to validate is empty");
862    		}
863    		if (issuerCertificates == null || issuerCertificates.length == 0) {
864    			throw new OCSPRequestGenerationException ("List of CA certificates to validate is empty");
865    		}
866    		if (certificates.length != issuerCertificates.length) {
867    			throw new OCSPRequestGenerationException ("List of certificates and CA certificates must have the same number of elements");
868    		}
869    		
870 		// Preparing the request
871 		OCSPReqBuilder constructorPeticion = new OCSPReqBuilder();
872         for (int i=0;i<certificates.length;i++) {
873 			// Generating the certificateId for request
874     		CertificateID identificadorCert;
875 			try {
876 				identificadorCert = new CertificateID(new JcaDigestCalculatorProviderBuilder().
877 						setProvider(CRYPTOGRAPHIC_PROVIDER_NAME).build().get(CertificateID.HASH_SHA1),
878 						new X509CertificateHolder(issuerCertificates [i].toDER()), certificates[i].getSerialNumberBigInteger());
879 			} catch (Exception e) {
880 	   			logger.info ("[OCSPClient.generateOCSPRequest] :: Cannot create a new certificate ID for the OCSP request", e);
881 	   			throw new OCSPRequestGenerationException ("Cannot create a new certificate ID for the OCSP request", e);
882 			} 
883 			
884 			// Adding the request certificate 
885 			constructorPeticion.addRequest(identificadorCert);
886         }
887         
888         // Requestor name
889         if (requestorName != null) {
890         	constructorPeticion.setRequestorName(new GeneralName (GeneralName.rfc822Name, requestorName));
891         }
892 		
893 		// Create the request
894    		OCSPReq peticionOCSP;
895 		try {
896 			if (keystore == null) {
897 				peticionOCSP = constructorPeticion.build();
898 			} else {
899 				PrivateKey pk = (PrivateKey) keystore.getKey(alias, aliasPassword.toCharArray());
900 				ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider(CRYPTOGRAPHIC_PROVIDER_NAME).build(pk);
901 				peticionOCSP = constructorPeticion.build(sha1Signer, new X509CertificateHolder[] { new X509CertificateHolder(keystore.getCertificate(alias).getEncoded()) });
902 			}
903 		} catch (Exception e) {
904    			logger.info ("[OCSPClient.generateOCSPRequest] :: Cannot create a new OCSP request", e);
905    			throw new OCSPRequestGenerationException ("Cannot create a new OCSP request", e);
906 		} 
907 		
908 		// Devolvemos la peticion codificada.
909 		try {
910 			return peticionOCSP.getEncoded();
911 		} catch (IOException e) {
912    			logger.info ("[OCSPClient.generateOCSPRequest] :: Cannot encode the OCSP request", e);
913    			throw new OCSPRequestGenerationException ("Cannot encode the OCSP request", e);
914 		}
915 			
916 	}
917 
918    	/**
919 	 * Genera una petición OCSP múltiple: se validarán varios certificados al mismo tiempo.
920 	 * La petición ser firmará.<br/><br/>
921 	 * 
922 	 * NOTA: Para que el método funcione es necesario que los certificados dispongan de extensión 
923 	 * 	Authority Key Identifier. De acuerdo al punto 4.2.1.1 de la RFC-3280 este campo es
924 	 * 	obligatorio salvo para certificados autofirmados, pero es posible encontrar certificados
925 	 * 	antiguos o no estandarizados que no dispongan de la extensión.
926    	 * 
927 	 * @param certificates Certificados a validar
928 	 * @param requestorName Nombre que identifica al llamador en el OCSP
929 	 * @param keystore Keystore abierto que contiene la clave privada que firma la petición
930 	 * @param alias Alias del keystore para firmar la petición
931 	 * @param aliasPassword Contraseña de la clave privada
932 	 * @return Array de bytes con la petición OCSP
933    	 * @throws OCSPRequestGenerationException Errores durante la generación
934    	 */
935    	public static  byte[] generateOCSPRequest(Certificate [] certificates,
936    			String requestorName, KeyStore keystore, String alias, String aliasPassword) throws OCSPRequestGenerationException{
937 		
938    		//-- Validate parameters
939    		if (certificates == null || certificates.length == 0) {
940    			throw new OCSPRequestGenerationException ("List of certificates to validate is empty");
941    		}
942    		
943 		// Preparing the request
944    		OCSPReqBuilder constructorPeticion = new OCSPReqBuilder();
945         for (int i=0;i<certificates.length;i++) {
946 			// Generating the certificateId for request
947     		CertificateID identificadorCert;
948 			try {
949 				identificadorCert = getCertificateID(certificates[i]);
950 			} catch (HashingException e) {
951 	   			logger.info ("[OCSPClient.generateOCSPRequest] :: Cannot create a new certificate ID for the OCSP request", e);
952 	   			throw new OCSPRequestGenerationException ("Cannot create a new certificate ID for the OCSP request", e);
953 			} 
954 			
955 			// Adding the request certificate 
956 			constructorPeticion.addRequest(identificadorCert);
957         }
958         
959         // Requestor name
960         if (requestorName != null) {
961         	constructorPeticion.setRequestorName(new GeneralName (GeneralName.rfc822Name, requestorName));
962         }
963 		
964 		// Create the request
965    		OCSPReq peticionOCSP;
966 		try {
967 			if (keystore == null) {
968 				peticionOCSP = constructorPeticion.build();
969 			} else {
970 				PrivateKey pk = (PrivateKey) keystore.getKey(alias, aliasPassword.toCharArray());
971 				ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider(CRYPTOGRAPHIC_PROVIDER_NAME).build(pk);
972 				peticionOCSP = constructorPeticion.build(sha1Signer, new X509CertificateHolder[] { new X509CertificateHolder(keystore.getCertificate(alias).getEncoded()) });
973 			}
974 		} catch (Exception e) {
975    			logger.info ("[OCSPClient.generateOCSPRequest] :: Cannot create a new OCSP request", e);
976    			throw new OCSPRequestGenerationException ("Cannot create a new OCSP request", e);
977 		} 
978 		
979 		// Devolvemos la peticion codificada.
980 		try {
981 			return peticionOCSP.getEncoded();
982 		} catch (IOException e) {
983    			logger.info ("[OCSPClient.generateOCSPRequest] :: Cannot encode the OCSP request", e);
984    			throw new OCSPRequestGenerationException ("Cannot encode the OCSP request", e);
985 		}
986 			
987 		
988 	}
989 
990 	/**
991    	 * Obtiene la URL de este OCSP
992    	 * 
993    	 * @return URL de este OCSP
994    	 */
995 	public URL getURL() {
996 		return this.urlOCSP;
997 	}
998 	
999    	/**
1000    	 * Obtiene un certificateID (utilizado para realizar peticiones OCSP) a partir 
1001    	 * de su certificado
1002    	 * 
1003    	 * @param certificate Certificado
1004    	 * @return CertificateID
1005    	 * @throws HashingException Error realizando el hash del campo issuerDN
1006    	 */
1007    	public static CertificateID getCertificateID (Certificate certificate) throws HashingException {
1008 		
1009    		//-- Obtener el algoritmo
1010    		AlgorithmIdentifier hashAlg = CertificateID.HASH_SHA1;
1011    		
1012    		//-- Obtener el hash del nombre del issuer
1013    		ByteArrayDocument document = new ByteArrayDocument(certificate.toX509Certificate().getIssuerX500Principal().getEncoded());
1014    		ASN1OctetString issuerNameHash = new DEROctetString(document.getHash(HashingAlgorithm.SHA1));
1015    		
1016    		//-- Obtener el hash de la clave publica del issuer (el authority key identifier)
1017    		ASN1OctetString issuerKeyHash = null;
1018    		if (certificate.getIssuerKeyIdentifier() != null) {
1019    			issuerKeyHash = new DEROctetString(Util.decodeBase64(certificate.getIssuerKeyIdentifier()));
1020    		}   		 
1021    		
1022    		//-- Obtener el CertId
1023    		CertID certId = new CertID(hashAlg, issuerNameHash, issuerKeyHash, new ASN1Integer(certificate.getSerialNumberBigInteger()));
1024    		
1025 		return new CertificateID(certId);
1026 	}
1027 
1028 	//-- Métodos privados
1029 	
1030 	/*
1031 	 * Obtiene la respuesta OCSP a partir de una petición OCSP
1032 	 */
1033    	private OCSPResponse getOCSPResponse (byte[] ocspRequest) throws OCSPServerConnectionException, MalformedOCSPResponseException, OCSPRequestGenerationException {
1034    		
1035    		logger.debug("[OCSPClient.getOCSPResponse] :: Entrada");
1036    		
1037    		//-- Init variables		
1038 		DataOutputStream dataOut = null;
1039 		HttpURLConnection httpConnection;
1040 		try {
1041 			httpConnection = (HttpURLConnection) urlOCSP.openConnection();
1042 		} catch (IOException e) {
1043    			logger.info ("[OCSPClient.getOCSPResponse] :: Unable to connect to " + urlOCSP, e);
1044    			throw new OCSPServerConnectionException ("Unable to connect to " + urlOCSP, e);
1045 		}
1046 		
1047 		// Setup the HTTP request			
1048 		httpConnection.setRequestProperty("Content-Type", "application/ocsp-request");	
1049 		httpConnection.setRequestProperty("Accept", "application/ocsp-response");
1050 		
1051 		httpConnection.setDoOutput(true);
1052         
1053         // Send the request
1054         try {
1055         	dataOut = new DataOutputStream(new BufferedOutputStream (httpConnection.getOutputStream()));
1056         	dataOut.write(ocspRequest, 0, ocspRequest.length);
1057         	dataOut.flush();
1058 		} catch (IOException e) {
1059    			logger.info ("[OCSPClient.getOCSPResponse] :: Error sending the OCSP request to: " + urlOCSP, e);
1060    			throw new OCSPServerConnectionException ("Error sending the OCSP request to: " + urlOCSP, e);
1061 		} finally {
1062 			if (dataOut != null) {
1063 				try { dataOut.close(); } catch (IOException e) { logger.info ("[OCSPClient.getOCSPResponse] :: No se puede cerrar el stream de escritura a " + urlOCSP, e); }
1064 			}
1065 		}
1066         
1067         // Check the HTTP response	        
1068         int lIntResponseCode;
1069 		try {
1070 			lIntResponseCode = httpConnection.getResponseCode();
1071 		} catch (IOException e) {
1072    			logger.info ("[OCSPClient.getOCSPResponse] :: Error getting the OCSP response code", e);
1073    			throw new OCSPServerConnectionException ("Error getting the OCSP response code", e);
1074 		}
1075         String 	lStrContentType = httpConnection.getContentType();
1076         if (lIntResponseCode==200 && lStrContentType != null && lStrContentType.equalsIgnoreCase("application/ocsp-response")) {	        
1077 	        // Process the result             
1078 	        int lLngLongitud = httpConnection.getContentLength();
1079 	        
1080 	        DataInputStream dataIn = null;
1081 	        byte[] lBytRespuesta;
1082 			try {
1083 				dataIn = new DataInputStream(httpConnection.getInputStream());
1084 		        lBytRespuesta = new byte[lLngLongitud];
1085 		     	dataIn.readFully(lBytRespuesta, 0, lBytRespuesta.length);	        
1086 		     	
1087 		     	// Get the response from OCSP
1088 		     	OCSPResp ocspResponse = new OCSPResp(lBytRespuesta);
1089 		     	
1090 		     	// Get possible error message
1091 		     	if (ocspResponse.getStatus() == OCSPRespBuilder.TRY_LATER) {
1092 		     		throw new OCSPException ("The OCSP response indicates that it will be try later");
1093 		     	}
1094 		     	if (ocspResponse.getStatus() == OCSPRespBuilder.INTERNAL_ERROR) {
1095 		     		throw new OCSPException ("The OCSP response indicates that there is an internal error in OCSP server");
1096 		     	}
1097 		     	if (ocspResponse.getStatus() == OCSPRespBuilder.MALFORMED_REQUEST) {
1098 		     		throw new OCSPException ("The OCSP response indicates that the request is malformed");
1099 		     	}
1100 		     	if (ocspResponse.getStatus() == OCSPRespBuilder.SIG_REQUIRED) {
1101 		     		throw new OCSPException ("The OCSP response indicates that the request must be signed");
1102 		     	}
1103 		     	if (ocspResponse.getStatus() == OCSPRespBuilder.UNAUTHORIZED) {
1104 		     		throw new OCSPException ("The OCSP response indicates that the request must contain authorization information");
1105 		     	}
1106 		     	
1107 		     	//-- Devolver la respuesta
1108 		     	return new OCSPResponse (ocspResponse);
1109 		     	
1110 			} catch (IOException e) {
1111 	   			logger.info ("[OCSPClient.getOCSPResponse] :: Cannot get the OCSP response", e);
1112 	   			throw new OCSPServerConnectionException ("Cannot get the the OCSP response", e);
1113 			} catch (OCSPException e) {
1114 	   			logger.info ("[OCSPClient.getOCSPResponse] :: Cannot get the OCSP basic response", e);
1115 	   			throw new OCSPServerConnectionException ("Cannot get the the OCSP basic response", e);
1116 			} finally {
1117 				if (dataIn != null) {
1118 					try { dataIn.close(); } catch (IOException e) { logger.info ("[OCSPClient.getOCSPResponse] :: No se puede cerrar el stream de lectura de " + urlOCSP, e); }
1119 				}
1120 			}
1121 	     	
1122         } else {
1123    			logger.info ("[OCSPClient.getOCSPResponse] :: HTTP response code is " + lIntResponseCode + ". Content type is " + lStrContentType);
1124    			throw new OCSPServerConnectionException ("HTTP response code is " + lIntResponseCode + ". Content type is " + lStrContentType);
1125         }
1126 	    
1127 	}
1128 
1129 }