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;
22  
23  import java.io.ByteArrayInputStream;
24  import java.io.File;
25  import java.io.FileNotFoundException;
26  import java.io.IOException;
27  import java.io.InputStream;
28  import java.math.BigInteger;
29  import java.net.MalformedURLException;
30  import java.net.URL;
31  import java.security.InvalidKeyException;
32  import java.security.MessageDigest;
33  import java.security.NoSuchAlgorithmException;
34  import java.security.NoSuchProviderException;
35  import java.security.PrivateKey;
36  import java.security.PublicKey;
37  import java.security.SecureRandom;
38  import java.security.SignatureException;
39  import java.security.cert.CertificateEncodingException;
40  import java.security.cert.CertificateException;
41  import java.security.cert.CertificateExpiredException;
42  import java.security.cert.CertificateFactory;
43  import java.security.cert.CertificateNotYetValidException;
44  import java.security.cert.CertificateParsingException;
45  import java.security.cert.X509Certificate;
46  import java.text.SimpleDateFormat;
47  import java.util.ArrayList;
48  import java.util.Arrays;
49  import java.util.Date;
50  import java.util.Enumeration;
51  import java.util.HashMap;
52  import java.util.Iterator;
53  import java.util.List;
54  import java.util.Map;
55  import java.util.StringTokenizer;
56  import java.util.TreeMap;
57  import java.util.Vector;
58  
59  import org.apache.log4j.Logger;
60  import org.bouncycastle.asn1.ASN1Encoding;
61  import org.bouncycastle.asn1.ASN1InputStream;
62  import org.bouncycastle.asn1.ASN1ObjectIdentifier;
63  import org.bouncycastle.asn1.ASN1OctetString;
64  import org.bouncycastle.asn1.ASN1Primitive;
65  import org.bouncycastle.asn1.ASN1Sequence;
66  import org.bouncycastle.asn1.ASN1String;
67  import org.bouncycastle.asn1.DERIA5String;
68  import org.bouncycastle.asn1.DEROctetString;
69  import org.bouncycastle.asn1.DERSequence;
70  import org.bouncycastle.asn1.DERTaggedObject;
71  import org.bouncycastle.asn1.DERUTF8String;
72  import org.bouncycastle.asn1.cms.ContentInfo;
73  import org.bouncycastle.asn1.cms.IssuerAndSerialNumber;
74  import org.bouncycastle.asn1.ocsp.OCSPObjectIdentifiers;
75  import org.bouncycastle.asn1.x500.RDN;
76  import org.bouncycastle.asn1.x500.X500Name;
77  import org.bouncycastle.asn1.x500.style.BCStyle;
78  import org.bouncycastle.asn1.x509.AccessDescription;
79  import org.bouncycastle.asn1.x509.AuthorityInformationAccess;
80  import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier;
81  import org.bouncycastle.asn1.x509.BasicConstraints;
82  import org.bouncycastle.asn1.x509.CRLDistPoint;
83  import org.bouncycastle.asn1.x509.DistributionPoint;
84  import org.bouncycastle.asn1.x509.DistributionPointName;
85  import org.bouncycastle.asn1.x509.Extension;
86  import org.bouncycastle.asn1.x509.GeneralName;
87  import org.bouncycastle.asn1.x509.GeneralNames;
88  import org.bouncycastle.asn1.x509.KeyUsage;
89  import org.bouncycastle.asn1.x509.PolicyInformation;
90  import org.bouncycastle.asn1.x509.SubjectKeyIdentifier;
91  import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
92  import org.bouncycastle.cert.CertIOException;
93  import org.bouncycastle.cert.X509CertificateHolder;
94  import org.bouncycastle.cert.X509v3CertificateBuilder;
95  import org.bouncycastle.cert.jcajce.JcaCertStore;
96  import org.bouncycastle.cms.CMSException;
97  import org.bouncycastle.cms.CMSProcessableByteArray;
98  import org.bouncycastle.cms.CMSSignedData;
99  import org.bouncycastle.cms.CMSSignedDataGenerator;
100 import org.bouncycastle.operator.ContentSigner;
101 import org.bouncycastle.operator.OperatorCreationException;
102 import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
103 import org.bouncycastle.util.encoders.Hex;
104 import org.ietf.ldap.LDAPDN;
105 
106 import es.accv.arangi.base.ArangiObject;
107 import es.accv.arangi.base.algorithm.DigitalSignatureAlgorithm;
108 import es.accv.arangi.base.algorithm.HashingAlgorithm;
109 import es.accv.arangi.base.certificate.data.CertificateDataService;
110 import es.accv.arangi.base.certificate.validation.CertificateValidationService;
111 import es.accv.arangi.base.certificate.validation.CertificateValidationServiceResult;
112 import es.accv.arangi.base.certificate.validation.OCSPClient;
113 import es.accv.arangi.base.certificate.validation.OCSPResponse;
114 import es.accv.arangi.base.exception.certificate.CertificateFieldException;
115 import es.accv.arangi.base.exception.certificate.NormalizeCertificateException;
116 import es.accv.arangi.base.util.AlternativeNameElement;
117 import es.accv.arangi.base.util.Util;
118 import es.accv.arangi.base.util.validation.ValidationResult;
119 
120 /**
121  * Clase base de todos los certificados de Arangi. Ofrece métodos para trabajar
122  * de forma cómoda con los diferentes campos del certificado.<br><br>
123  * 
124  * Los certificados permitidos son aquellos que cumplen el estándar definido en
125  * la <a href="http://tools.ietf.org/rfc/rfc5280.txt" target="rfc">RFC-5280</a>: x.509 v3.
126  * 
127  * @author <a href="mailto:jgutierrez@accv.es">José M Gutiérrez</a>
128  */
129 public class Certificate extends ArangiObject{
130 
131 	/**
132 	 * Logger de la clase
133 	 */
134 	static Logger logger = Logger.getLogger(Certificate.class);
135 	
136 	/**
137 	 * OID del campo OCSP de la extensión AIA
138 	 */
139 	public static final String OID_OCSP_AIA_EXTENSION	= "1.3.6.1.5.5.7.48.1";
140 	
141 	/**
142 	 * OID del campo id-at-commonName
143 	 */
144 	public static final String OID_ID_AT_COMMONNAME	= "2.5.4.3";
145 	
146 	/**
147 	 * OID del campo Userid
148 	 */
149 	public static final String OID_USERID	= "0.9.2342.19200300.100.1.1";
150 	
151     private static final String[] DN_OBJECTS = {
152         "unstructuredaddress", "unstructuredname", "emailaddress", "e", "email", "uid", "cn", "sn", "serialnumber", "gn", "givenname",
153         "initials", "surname", "t", "ou", "o", "l", "st", "dc", "c"
154     };
155     
156 	/*
157 	 * Date parser
158 	 */
159 	protected static SimpleDateFormat dateFormat = new SimpleDateFormat ("yyyy-MM-dd HH:mm");
160 	
161 	/**
162 	 * Objeto certificado en X.509 al que recubre esta clase
163 	 */
164 	protected X509Certificate certificate;
165 	
166 	/**
167 	 * Representación del certificado en ASN1
168 	 */
169 	org.bouncycastle.asn1.x509.Certificate asn1Certificate;
170 	
171 	/**
172 	 * Flag que indica si el certificado está autofirmado
173 	 */
174 	private Boolean selfSigned;
175 	
176     /** BC X509Name contains some lookup tables that could maybe be used here. */
177     private static final HashMap<String,ASN1ObjectIdentifier> oids = new HashMap<String,ASN1ObjectIdentifier>();
178 
179     static {
180         oids.put("c", BCStyle.C);
181         oids.put("dc", BCStyle.DC);
182         oids.put("st", BCStyle.ST);
183         oids.put("l", BCStyle.L);
184         oids.put("o", BCStyle.O);
185         oids.put("ou", BCStyle.OU);
186         oids.put("t", BCStyle.T);
187         oids.put("surname", BCStyle.SURNAME);
188         oids.put("initials", BCStyle.INITIALS);
189         oids.put("givenname", BCStyle.GIVENNAME);
190         oids.put("gn", BCStyle.GIVENNAME);
191         oids.put("sn", BCStyle.SN);
192         oids.put("serialnumber", BCStyle.SN);
193         oids.put("cn", BCStyle.CN);
194         oids.put("uid", BCStyle.UID);
195         oids.put("emailaddress", BCStyle.EmailAddress);
196         oids.put("e", BCStyle.EmailAddress);
197         oids.put("email", BCStyle.EmailAddress);
198         oids.put("unstructuredname", BCStyle.UnstructuredName); //unstructuredName 
199         oids.put("unstructuredaddress", BCStyle.UnstructuredAddress); //unstructuredAddress
200     }
201     
202     private static final String[] dNObjects = {
203         "unstructuredaddress", "unstructuredname", "emailaddress", "e", "email", "uid", "cn", "sn", "serialnumber", "gn", "givenname",
204         "initials", "surname", "t", "ou", "o", "l", "st", "dc", "c"
205     };
206     
207 	/**
208 	 * Constructor que inicializa la clase mediante un certificado en formato
209 	 * X.509
210 	 * 
211 	 * @param certificate Certificado en formato X.509
212 	 * @throws NormalizeCertificateException No se ha podido normalizar el certificado para
213 	 * 	ser usado con el proveedor criptográfico de Arangi
214 	 */
215 	public Certificate(X509CertificateHolder certificate) throws NormalizeCertificateException {
216 		super();
217 		
218 		try {
219 			initialize (Util.getCertificate(certificate));
220 		} catch (CertificateException e) {
221 			logger.info("[Certificate]::No se puede pasar de la estructura al certificado X.509");
222 			throw new NormalizeCertificateException("No se puede pasar de la estructura al certificado X.509");
223 		}
224 	}
225 	
226 	/**
227 	 * Constructor que inicializa la clase mediante un certificado en formato
228 	 * X.509
229 	 * 
230 	 * @param certificate Certificado en formato X.509
231 	 * @throws NormalizeCertificateException No se ha podido normalizar el certificado para
232 	 * 	ser usado con el proveedor criptográfico de Arangi
233 	 */
234 	public Certificate(X509Certificate certificate) throws NormalizeCertificateException {
235 		super();
236 		
237 		initialize (certificate);
238 	}
239 	
240 	/**
241 	 * Constructor que inicializa la clase mediante un fichero. El fichero debe contener
242 	 * un certificado X.509 (tal cual o en formato PEM)
243 	 * 
244 	 * @param fileCertificate Fichero que contiene un certificado en formato X.509
245 	 * @throws NormalizeCertificateException No se ha podido normalizar el certificado para
246 	 * 	ser usado con el proveedor criptográfico de Arangi
247 	 * @throws FileNotFoundException El fichero no existe
248 	 */
249 	public Certificate(File fileCertificate) throws NormalizeCertificateException, FileNotFoundException {
250 		super();
251 		
252 		//-- Obtener el certificado
253 		X509Certificate certificate = Util.getCertificate(fileCertificate);
254 		if (certificate == null) {
255 			logger.info("[Certificate]::El fichero no es un certificado digital");
256 			throw new NormalizeCertificateException("El fichero no es un certificado digital");
257 		}
258 		
259 		//-- Cargar el certificado
260 		this.certificate = normalize (certificate);
261 		
262 		//-- Inicializar
263 		initialize(certificate);
264 	}
265 	
266 	/**
267 	 * Constructor que inicializa la clase a partir de un stream de lectura. El stream debe 
268 	 * contener un certificado X.509 (tal cual o en formato PEM)
269 	 * 
270 	 * @param isCertificate Stream de lectura a un certificado en formato X.509
271 	 * @throws NormalizeCertificateException No se ha podido normalizar el certificado para
272 	 * 	ser usado con el proveedor criptográfico de Arangi
273 	 */
274 	public Certificate(InputStream isCertificate) throws NormalizeCertificateException {
275 		super();
276 		
277 		//-- Obtener el certificado
278 		X509Certificate certificate = Util.getCertificate(isCertificate);
279 		if (certificate == null) {
280 			logger.info("[Certificate]::El fichero no es un certificado digital");
281 			throw new NormalizeCertificateException("El fichero no es un certificado digital");
282 		}
283 		
284 		//-- Cargar el certificado
285 		this.certificate = normalize (certificate);
286 		
287 		//-- Inicializar
288 		initialize(certificate);
289 	}
290 	
291 	/**
292 	 * Constructor que inicializa la clase a partir de un array de bytes. Los bytes deben 
293 	 * ser el contenido de un certificado X.509 (tal cual o en formato PEM)
294 	 * 
295 	 * @param contenidoCertificado Contenido de un certificado en formato X.509
296 	 * @throws NormalizeCertificateException No se ha podido normalizar el certificado para
297 	 * 	ser usado con el proveedor criptográfico de Arangi
298 	 */
299 	public Certificate(byte[] contenidoCertificado) throws NormalizeCertificateException {
300 		super();
301 		
302 		//-- Obtener el certificado
303 		ByteArrayInputStream bais = new ByteArrayInputStream (contenidoCertificado);
304 		X509Certificate certificate = Util.getCertificate(bais);
305 		if (certificate == null) {
306 			logger.info("[Certificate]::El fichero no es un certificado digital");
307 			throw new NormalizeCertificateException("El fichero no es un certificado digital");
308 		}
309 		
310 		//-- Cargar el certificado
311 		this.certificate = normalize (certificate);
312 		
313 		//-- Inicializar
314 		initialize(certificate);
315 	}
316 	
317 
318 	//-- Métodos públicos
319 	
320 	/**
321 	 * Método que devuelve si el certificado es autofirmado
322 	 * 
323 	 * @return Cierto si está autofirmado
324 	 * @throws NormalizeCertificateException Errores en la firma del certificado
325 	 */
326 	public boolean isSelfSigned() throws NormalizeCertificateException {
327 		logger.debug("[Certificate.isSelfSigned]:: Inicio ");
328 
329 		if (this.selfSigned == null) {
330 			PublicKey pubKey = certificate.getPublicKey();
331 			try {
332 				certificate.verify(pubKey, CRYPTOGRAPHIC_PROVIDER_NAME);
333 				logger.debug("[Certificate.isSelfSigned]::Es autofirmado ");
334 				
335 				this.selfSigned = new Boolean (true);
336 	
337 			} catch (InvalidKeyException e) {
338 				// Is not self signed
339 				logger.debug("[Certificate.isSelfSigned]::No es autofirmado");
340 				this.selfSigned = new Boolean (false);
341 			} catch (CertificateException e) {
342 				logger.info ("[Certificate.isSelfSigned]::La firma del certificado no está correctamente codificada", e);
343 				throw new NormalizeCertificateException ("La firma del certificado no está correctamente codificada", e);
344 			} catch (NoSuchAlgorithmException e) {
345 				logger.info ("[Certificate.isSelfSigned]::El algoritmo de la firma del certificado no está soportado", e);
346 				throw new NormalizeCertificateException ("El algoritmo de la firma del certificado no está soportado", e);
347 			} catch (NoSuchProviderException e) {
348 				//-- No se debería dar
349 				logger.info ("[Certificate.isSelfSigned]::No existe el proveedor criptográfico de Arangi", e);
350 				throw new NormalizeCertificateException ("No existe el proveedor criptográfico de Arangi", e);
351 			} catch (SignatureException e) {
352 				// Is not self signed
353 				logger.debug("[Certificate.isSelfSigned]::No es autofirmado");
354 				this.selfSigned = new Boolean (false);
355 			} 
356 		}
357 		
358 		return this.selfSigned.booleanValue();
359 	}
360 
361 	/**
362 	 * Método que obtiene el OID de la política del certificado. 
363 	 * 
364 	 * @return OID de la política del certificado o nulo si no existe la
365 	 * 	extensión CertificatePolicies
366 	 */
367 	public String getPolicyOID() {
368 		
369 		logger.debug("[Certificate.getPolicyOID]::Entrada");
370 
371 		List<String> policyOIDs = getPolicyOIDs();
372 		if (policyOIDs.isEmpty()) {
373 			return null;
374 		}
375 		
376 		return policyOIDs.get(0);
377 	}
378 	
379 	/**
380 	 * Método que obtiene los OIDs de la política del certificado. 
381 	 * 
382 	 * @return OIDs de la política del certificado
383 	 */
384 	public List<String> getPolicyOIDs() {
385 		
386 		logger.debug("[Certificate.getPolicyOIDs]::Entrada");
387 		
388 		List<String> policyOIDs = new ArrayList<String>();
389 
390 		//-- Accedemos a la extensión del certificatePolicies.
391 		byte[] extension = certificate.getExtensionValue(Extension.certificatePolicies.getId());
392 		
393 		if (extension == null) {
394 			return policyOIDs;
395 		}
396 		//-- Obtenemos las políticas
397 		try {
398 			ByteArrayInputStream bais = new ByteArrayInputStream(extension);
399 			ASN1InputStream asn1IS = new ASN1InputStream(bais);
400 			
401 			bais = new ByteArrayInputStream(((ASN1OctetString) asn1IS.readObject()).getOctets());
402 			asn1IS = new ASN1InputStream(bais);
403 			
404 			Enumeration enumeration = ((ASN1Sequence) asn1IS.readObject()).getObjects();
405 			while (enumeration.hasMoreElements()) {
406 				Enumeration enumeration2 = ((ASN1Sequence) enumeration.nextElement()).getObjects();
407 			
408 				String policy = ((ASN1ObjectIdentifier) enumeration2.nextElement()).getId();
409 				logger.debug("[Certificate.getPolicyOIDs]::Una política del certificado es" + policy);
410 				policyOIDs.add(policy);
411 			}
412 			
413 			return policyOIDs;
414 			
415 		} catch (Exception e) {
416 			logger.info("[Certificate.getPolicyOIDs]::No es posible obtener la extensión del certificado", e);
417 			return new ArrayList<String>();
418 		}
419 	}
420 	
421 	/**
422 	 * Método que obtiene el Issuer Key Identifier (IKI) del certificado
423 	 * 
424 	 * @return Issuer Key Identifier o nulo si éste no se pudo obtener del certificado
425 	 */
426 	public String getIssuerKeyIdentifier()  {
427 		return Certificate.getIssuerKeyIdentifier(this.certificate);
428 	}
429 
430 	/**
431 	 * Método que obtiene el Subject Key Identifier (SKI) a partir del certificado
432 	 * 
433 	 * @return Subject Key Identifier o nulo si éste no se pudo obtener del certificado
434 	 */
435 	public String getSubjectKeyIdentifier() { 
436 		return Certificate.getSubjectKeyIdentifier(this.certificate);
437 	}
438 	
439 	/**
440 	 * El método obtiene las URLs de las CRLs indicadas en el certificado. Para ello consulta
441 	 * la extensión CRL Distribution Points (CDP). Si dicha extensión no existe se devolverá
442 	 * un array sin ningún elemento. 
443 	 * 
444 	 * @return URLs de las CRLs del certificado
445 	 * @throws CertificateFieldException Existe la extensión CDP pero no se puede leer 
446 	 */
447 	public String [] getCrlUrls() throws CertificateFieldException{
448 		
449 		logger.debug("[Certificate.getCrlUrls]::Entrada");
450 		
451 		DERIA5String lDERObjCRL_URL;
452 		byte[] extBytes = certificate.getExtensionValue(Extension.cRLDistributionPoints.getId());
453 		
454 		// En caso de no tener contenido, devolvemos un array vacío.
455 		if (extBytes == null) {
456 			logger.debug("[Certificate.getCrlUrls]::No existe la extensión CDP en el certificado");
457 			return new String[0];
458 		}
459 		
460 		// Load ASN1 object
461 		ASN1InputStream ais = new ASN1InputStream(new ByteArrayInputStream(extBytes));
462 		
463 		try {
464 			DEROctetString oct = (DEROctetString) ais.readObject();
465 			ais = new ASN1InputStream(new ByteArrayInputStream(oct.getOctets()));
466 			CRLDistPoint cdp = CRLDistPoint.getInstance((ASN1Sequence) ais.readObject());
467 			// [BC-135] - point.getDistributionPoints();
468 			DistributionPoint[] points = cdp.getDistributionPoints();
469 			
470 			ArrayList alURLs = new ArrayList();
471 			for (int i = 0; i < points.length; i++) {
472 				DistributionPoint point = points[i];
473 				// [BC-135] - point.getDistributionPoint();
474 				DistributionPointName name = point.getDistributionPoint();
475 				// [BC-135] - getName() y getNames()
476 				GeneralName[] gns = ((GeneralNames) name.getName()).getNames();
477 				for (int j = 0; j < gns.length; j++) {
478 					GeneralName gn = gns[j];
479 					// Si lo que nos llega es una URL, se manda la URL extraida
480 					// [BC-135] - GeneralName.uniformResourceIdentifier
481 					if (gn.getTagNo() == GeneralName.uniformResourceIdentifier) {
482 						lDERObjCRL_URL = (DERIA5String) ((DERTaggedObject)gn.toASN1Primitive().toASN1Primitive()).getObject(); 
483 						alURLs.add (lDERObjCRL_URL.getString());
484 					} else if (gn.getTagNo() == GeneralName.directoryName) {
485 					}
486 				}
487 			}
488 			
489 			//-- Return list of CRL URLs
490 			return (String []) alURLs.toArray(new String [0]);
491 		
492 		} catch (IOException e) {
493 			logger.info("[Certificate.getCrlUrls]::La extensión CDP en el certificado existe pero no se puede leer", e);
494 			throw new CertificateFieldException ("La extensión CDP en el certificado existe pero no se puede leer", e);
495 		}
496 	}
497 	
498 	/**
499 	 * El método obtiene las URLs de los OCSPs que se indican en el certificado. Para ello consulta
500 	 * la extensión Authority Info Access (AIA). Si dicha extensión no existe se devolverá
501 	 * un array sin ningún elemento. 
502 	 * 
503 	 * @return URLs de los OCSPs del certificado
504 	 * @throws CertificateFieldException Existe la extensión AIA pero no se puede leer 
505 	 */
506 	public String [] getOcspUrls() throws CertificateFieldException{
507 		
508 		byte[] extBytes = certificate.getExtensionValue(Extension.authorityInfoAccess.getId());
509 		
510 		// En caso de no tener contenido, devolvemos una cadena vacia. Deberíamos lanzar una excepcion.
511 		if (extBytes == null) {
512 			logger.debug("[Certificate.getCrlUrls]::No existe la extensión AIA en el certificado");
513 			return new String[0];
514 		}
515 		
516 		// Load ASN1 object
517 		ASN1InputStream ais = new ASN1InputStream(new ByteArrayInputStream(extBytes));
518 		
519 		try {
520 			DEROctetString oct = (DEROctetString) ais.readObject();
521 			ais = new ASN1InputStream(new ByteArrayInputStream(oct.getOctets()));
522 			AuthorityInformationAccess aia = AuthorityInformationAccess.getInstance((ASN1Sequence) ais.readObject());
523 			List<String> urls = new ArrayList<String>();
524 			for (int i=0; i<aia.getAccessDescriptions().length; i++) {
525 				AccessDescription accessDescription = aia.getAccessDescriptions() [i];
526 				if (accessDescription.getAccessLocation().getTagNo() == GeneralName.uniformResourceIdentifier &&
527 						accessDescription.getAccessMethod().getId().equals(OID_OCSP_AIA_EXTENSION)) {
528 					DERIA5String lDERObjCRL_URL = (DERIA5String) ((DERTaggedObject)accessDescription.getAccessLocation().toASN1Primitive()).getObject();
529 					urls.add(lDERObjCRL_URL.getString());
530 				}
531 			}
532 
533 			return (String[]) urls.toArray(new String[0]);
534 			
535 		} catch (IOException e) {
536 			logger.info("[Certificate.getCrlUrls]::La extensión AIA en el certificado existe pero no se puede leer", e);
537 			throw new CertificateFieldException ("La extensión AIA en el certificado existe pero no se puede leer", e);
538 		}
539 	}
540 	
541 	/**
542 	 * Método que comprueba la validez del certificado respecto a la fecha y hora
543 	 * actual del sistema. 
544 	 * 
545 	 * @return cierto si el fichero está dentro de su intervalo de validez
546 	 */
547 	public boolean isActive() {
548 		
549 		logger.debug ("[Certificate.isCertificateInValidityInterval]::Entrada");
550 		
551 		try {
552 			certificate.checkValidity();
553 		} catch (CertificateNotYetValidException e) {
554 			logger.debug ("[Certificate.isCertificateInValidityInterval]::El certificado aun no es válido");
555 			return false;
556 		} catch (CertificateExpiredException e) {
557 			logger.debug ("[Certificate.isCertificateInValidityInterval]::El certificado ya no es válido");
558 			return false;
559 	    }
560 
561 	    return true;
562 	}
563 	
564 	/**
565 	 * Método que comprueba si el certificado aun no ha llegado a su periodo de
566 	 * validez.
567 	 * 
568 	 * @return cierto si el fichero aún no ha llegado a su periodo de validez
569 	 */
570 	public boolean isNotYetActive() {
571 		
572 		logger.debug ("[Certificate.isNotYetActive]::Entrada");
573 		
574 		try {
575 			certificate.checkValidity();
576 		} catch (CertificateNotYetValidException e) {
577 			logger.debug ("[Certificate.isNotYetActive]::El certificado aun no es válido");
578 			return true;
579 		} catch (CertificateExpiredException e) {
580 			logger.debug ("[Certificate.isNotYetActive]::El certificado ya no es válido");
581 			return false;
582 	    }
583 
584 	    return false;
585 	}
586 	
587 	/**
588 	 * Método que comprueba si el certificado ya está caducado: ha sobrepasado su periodo
589 	 * de validez
590 	 * 
591 	 * @return cierto si el fichero está caducado
592 	 */
593 	public boolean isExpired() {
594 		
595 		logger.debug ("[Certificate.isExpired]::Entrada");
596 		
597 		try {
598 			certificate.checkValidity();
599 		} catch (CertificateNotYetValidException e) {
600 			logger.debug ("[Certificate.isExpired]::El certificado aun no es válido");
601 			return false;
602 		} catch (CertificateExpiredException e) {
603 			logger.debug ("[Certificate.isExpired]::El certificado ya no es válido");
604 			return true;
605 	    }
606 
607 	    return false;
608 	}
609 	
610 	/**
611 	 * Obtiene la fecha de comienzo del periodo de validez del certificado
612 	 * 
613 	 * @return Fecha de comienzo del periodo de validez del certificado
614 	 */
615 	public Date getValidityPeriodBeginning () {
616 		
617 		logger.debug ("[Certificate.getValidityPeriodBeginning]::Entrada");
618 		
619 		return certificate.getNotBefore();
620 	}
621 	
622 	/**
623 	 * Obtiene la fecha de finalización del periodo de validez del certificado
624 	 * 
625 	 * @return Fecha de finalización del periodo de validez del certificado
626 	 */
627 	public Date getValidityPeriodEnd () {
628 		
629 		logger.debug ("[Certificate.getValidityPeriodEnd]::Entrada");
630 		
631 		return certificate.getNotAfter();
632 	}
633 	
634 	/**
635 	 * Comprueba si el certificado tiene como uso de clave la firma digital
636 	 * 
637 	 * @return Cierto si el certificado tiene como uso de clave la firma digital
638 	 */
639 	public boolean isKeyUsageDigitalSignature () {
640 		
641 		logger.debug ("[Certificate.isKeyUsageDigitalSignature]::Entrada");
642 		
643 		if (certificate.getKeyUsage() == null) {
644 			return true;
645 		}
646 		
647 		return certificate.getKeyUsage()[0];
648 	}
649 	
650 	/**
651 	 * Comprueba si el certificado tiene como uso de clave el no repudio
652 	 * 
653 	 * @return Cierto si el certificado tiene como uso de clave el no repudio
654 	 */
655 	public boolean isKeyUsageNonRepudiation () {
656 		
657 		logger.debug ("[Certificate.isKeyUsageNonRepudiation]::Entrada");
658 		
659 		if (certificate.getKeyUsage() == null) {
660 			return true;
661 		}
662 		
663 		return certificate.getKeyUsage()[1];
664 	}
665 	
666 	/**
667 	 * Comprueba si el certificado tiene como uso de clave el cifrado de claves
668 	 * 
669 	 * @return Cierto si el certificado tiene como uso de clave el cifrado de claves
670 	 */
671 	public boolean isKeyUsageKeyEncipherment () {
672 		
673 		logger.debug ("[Certificate.isKeyUsageKeyEncipherment]::Entrada");
674 		
675 		if (certificate.getKeyUsage() == null) {
676 			return true;
677 		}
678 		
679 		return certificate.getKeyUsage()[2];
680 	}
681 	
682 	/**
683 	 * Comprueba si el certificado tiene como uso de clave el cifrado de datos
684 	 * 
685 	 * @return Cierto si el certificado tiene como uso de clave el cifrado de datos
686 	 */
687 	public boolean isKeyUsageDataEncipherment () {
688 		
689 		logger.debug ("[Certificate.isKeyUsageDataEncipherment]::Entrada");
690 		
691 		if (certificate.getKeyUsage() == null) {
692 			return true;
693 		}
694 		
695 		return certificate.getKeyUsage()[3];
696 	}
697 	
698 	/**
699 	 * Comprueba si el certificado tiene como uso de clave el acuerdo de claves
700 	 * 
701 	 * @return Cierto si el certificado tiene como uso de clave el acuerdo de claves
702 	 */
703 	public boolean isKeyUsageKeyAgreement () {
704 		
705 		logger.debug ("[Certificate.isKeyUsageKeyAgreement]::Entrada");
706 		
707 		if (certificate.getKeyUsage() == null) {
708 			return true;
709 		}
710 		
711 		return certificate.getKeyUsage()[4];
712 	}
713 	
714 	/**
715 	 * Comprueba si el certificado tiene como uso de clave la firma de certificados
716 	 * 
717 	 * @return Cierto si el certificado tiene como uso de clave la firma de certificados
718 	 */
719 	public boolean isKeyUsageKeyCertSign () {
720 		
721 		logger.debug ("[Certificate.isKeyUsageKeyCertSign]::Entrada");
722 		
723 		if (certificate.getKeyUsage() == null) {
724 			return true;
725 		}
726 		
727 		return certificate.getKeyUsage()[5];
728 	}
729 	
730 	/**
731 	 * Comprueba si el certificado tiene como uso de clave la firma de CRLs
732 	 * 
733 	 * @return Cierto si el certificado tiene como uso de clave la firma de CRLs
734 	 */
735 	public boolean isKeyUsageCRLSign () {
736 		
737 		logger.debug ("[Certificate.isKeyUsageCRLSign]::Entrada");
738 		
739 		if (certificate.getKeyUsage() == null) {
740 			return true;
741 		}
742 		
743 		return certificate.getKeyUsage()[6];
744 	}
745 	
746 	/**
747 	 * Comprueba si el certificado tiene como uso de clave sólo el cifrado
748 	 * 
749 	 * @return Cierto si el certificado tiene como uso de clave sólo el cifrado
750 	 */
751 	public boolean isKeyUsageEncipherOnly () {
752 		
753 		logger.debug ("[Certificate.isKeyUsageEncipherOnly]::Entrada");
754 		
755 		if (certificate.getKeyUsage() == null) {
756 			return true;
757 		}
758 		
759 		return certificate.getKeyUsage()[7];
760 	}
761 	
762 	/**
763 	 * Comprueba si el certificado tiene como uso de clave sólo el descifrado
764 	 * 
765 	 * @return Cierto si el certificado tiene como uso de clave sólo el descifrado
766 	 */
767 	public boolean isKeyUsageDecipherOnly () {
768 		
769 		logger.debug ("[Certificate.isKeyUsageDecipherOnly]::Entrada");
770 		
771 		if (certificate.getKeyUsage() == null) {
772 			return true;
773 		}
774 		
775 		return certificate.getKeyUsage()[8];
776 	}
777 	
778 	/**
779 	 * Obtiene la lista de usos de clave extendidos. Las constantes con los tipos
780 	 * definidos en el estándar se encuentran en org.bouncycastle.asn1.x509.KeyPurposeId.
781 	 * Por ejemplo, si queremos saber si el certificado tiene la extensión de firma de
782 	 * OCSP:
783 	 * <code>
784 	 * 	if (certificate.getExtendedKeyUsage().contains (KeyPurposeId.id_kp_OCSPSigning.getId())) { ... }
785 	 * </code>
786 	 * 
787 	 * @return Lista de usos de clave extendidos
788 	 * @throws CertificateException La extensión no puede ser descodificada
789 	 */
790 	public List<String> getExtendedKeyUsage () throws es.accv.arangi.base.exception.CertificateException {
791 		
792 		logger.debug ("[Certificate.getExtendedKeyUsage]::Entrada");
793 		
794 		try {
795 			List<String> result = certificate.getExtendedKeyUsage();
796 			if (result == null) {
797 				return new ArrayList<String>();
798 			}
799 			return result;
800 		} catch (CertificateParsingException e) {
801 			logger.info("[Certificate.getExtendedKeyUsage]::La extensión no puede ser descodificada", e);
802 			throw new es.accv.arangi.base.exception.CertificateException("La extensión no puede ser descodificada", e);
803 		} 
804 	}
805 	
806 	/**
807 	 * Método que devuelve la huella Digital (FingerPrint) del certificado. Es
808 	 * el mismo resultado de llamar a {@link #getDigest(java.lang.String) getDigest} más
809 	 * una transformación del resultado a hexadecimal.<br><br>
810 	 * 
811 	 * El FingerPrint ha sido creado utilizando como algoritmo de hashing "SHA1".
812 	 * 
813 	 * @return String que contienen la huella digital del certificado.
814 	 */
815 	public String getFingerPrint() {
816 		return getFingerPrint(DEFAULT_HASHING_ALGORITHM);
817 	}
818 	
819 	/**
820 	 * Método que devuelve la huella Digital (FingerPrint) del certificado. Es
821 	 * el mismo resultado de llamar a {@link #getDigest(java.lang.String) getDigest} más
822 	 * una transformación del resultado a hexadecimal.
823 	 * 
824 	 * @param hashingAlgorithm Algoritmo de hash a utilizar
825 	 * @return String que contienen la huella digital del certificado.
826 	 */
827 	public String getFingerPrint(String hashingAlgorithm) {
828 		
829 		logger.debug ("[Certificate.getFingerPrint]::Entrada");
830 
831 	    try {
832 	    	// Obtenemos el hash del certificado
833 	    	byte[] lBytesHash = getDigest(hashingAlgorithm);
834 	    	
835 	    	// Convertimos a Hexadecimal...
836 	    	byte[] lBytesHash_HEX = Hex.encode(lBytesHash);
837 	    	
838 	    	// Obtenemos la representación en String del Hash en Hexadecimal...
839 	    	String lStrHash = new String(lBytesHash_HEX);
840 	    	
841 	    	return lStrHash.toUpperCase();
842 	    } catch (CertificateEncodingException e0) {
843 	    	logger.info ("[Certificate.getFingerPrint]::Error de codificación del certificado");
844 	    	return "";
845 	    } catch (NoSuchAlgorithmException e2) {
846 	    	logger.info ("[Certificate.getFingerPrint]::No se encuentra el algoritmo " + DEFAULT_HASHING_ALGORITHM);
847 	    	return "";
848 	    }
849 	}
850 	
851 	/**
852 	 * Método que devuelve el digest del certificado.<br><br>
853 	 * 
854 	 * El digest ha sido creado utilizando con el algoritmo de hashing "SHA1".
855 	 * 
856 	 * @return String que contienen el digest del certificado.
857 	 * @throws NoSuchAlgorithmException No existe el algoritmo de hashing para
858 	 * 	el proveedor criptográfico de Arangí
859 	 * @throws CertificateEncodingException Error obteniendo la codificación
860 	 * 	DER del documento
861 	 */
862 	public byte[] getDigest() throws CertificateEncodingException, NoSuchAlgorithmException {
863 		return getDigest(DEFAULT_HASHING_ALGORITHM);
864 	}
865 	
866 	/**
867 	 * Método que devuelve el digest del certificado.
868 	 * 
869 	 * @param hashingAlgorithm Algoritmo de hash a utilizar
870 	 * @return String que contienen el digest del certificado.
871 	 * @throws NoSuchAlgorithmException No existe el algoritmo de hashing para
872 	 * 	el proveedor criptográfico de Arangí
873 	 * @throws CertificateEncodingException Error obteniendo la codificación
874 	 * 	DER del documento
875 	 */
876 	public byte[] getDigest(String hashingAlgorithm) throws NoSuchAlgorithmException, CertificateEncodingException {
877 		
878 		logger.debug ("[Certificate.getDigest]::Entrada::" + hashingAlgorithm);
879 
880     	// Obtenemos un objeto para crear "hash" de datos utilizando una
881     	MessageDigest lObjHashMaker = MessageDigest.getInstance(hashingAlgorithm);
882     	
883     	// Obtenemos el hash del certificado
884     	return lObjHashMaker.digest(certificate.getEncoded());
885 	    	
886 	}
887 	
888 	/**
889 	 * Obtiene el algoritmo de hashing de la firma del certificado
890 	 * 
891 	 * @return Algoritmo de hashing de la firma del certificado
892 	 * @throws NoSuchAlgorithmException el algoritmo no existe
893 	 */
894 	public String getDigestAlgorithm () throws NoSuchAlgorithmException {
895 		String sigAlgorithm = certificate.getSigAlgName();
896 		logger.debug("Algoritmo de firma del certificado: " + sigAlgorithm);
897 		return DigitalSignatureAlgorithm.getHashingAlgorithm(sigAlgorithm);
898 	}
899 	
900 	/**
901 	 * Obtiene el primer elemento del Asunto (Subject) del certificado para el OID.<br><br>
902 	 * 
903 	 * Por ejemplo, para obtener el campo GIVENNAME (G) del Asunto (Subject):<br>
904 	 * <code>
905 	 * 	certificate.getElementSubject(X509Name.GIVENNAME)
906 	 * </code>
907 	 * 
908 	 * @param oid OID dele elemento buscado
909 	 * @return Valor del elemento
910 	 */
911 	public String getElementSubject (ASN1ObjectIdentifier oid) {
912 		
913 		logger.debug ("[Certificate.getElementSubject]::Buscando OID '" + oid.getId() + "' en el subject");
914 
915 		X500Name subjectName = this.asn1Certificate.getSubject();
916 		RDN[] rdns = subjectName.getRDNs(oid);
917 		if (rdns == null || rdns.length == 0) {
918 			logger.debug ("[Certificate.getElementSubject]::Para el OID '" + oid.getId() + "' no hay ningún elemento en el subject");
919 			return null;
920 		}
921 		return rdns[0].getFirst().getValue().toString();
922 	}
923 
924 	/**
925 	 * Obtiene elementos del Asunto (Subject) del certificado en base a su OID.<br><br>
926 	 * 
927 	 * Por ejemplo, para obtener el campo GIVENNAME (G) del Asunto (Subject):<br>
928 	 * <code>
929 	 * 	certificate.getElementSubject(X509Name.GIVENNAME)
930 	 * </code>
931 	 * 
932 	 * @param oid OID dele elemento buscado
933 	 * @return Valor del elemento
934 	 */
935 	public String[] getElementsSubject (ASN1ObjectIdentifier oid) {
936 		
937 		logger.debug ("[Certificate.getElementSubject]::Buscando OID '" + oid.getId() + "' en el subject");
938 
939 		X500Name subjectName = this.asn1Certificate.getSubject();
940 		RDN[] rdns = subjectName.getRDNs(oid);
941 		if (rdns == null || rdns.length == 0) {
942 			logger.debug ("[Certificate.getElementSubject]::Para el OID '" + oid.getId() + "' no hay ningún elemento en el subject");
943 			return null;
944 		}
945 		String[] result = new String[rdns.length];
946 		for(int i=0;i<rdns.length;i++) {
947 			result[i] = rdns[i].getFirst().getValue().toString();
948 		}
949 		return result;
950 	}
951 
952 	/**
953 	 * Obtiene el common name que se encuentra en el asunto del certificado
954 	 * 
955 	 * @return Common Name
956 	 */
957 	public String getCommonName () {
958 		
959 		logger.debug ("[Certificate.getCommonName]::Entrada");
960 		
961 		return getElementSubject(BCStyle.CN);
962 	}
963 	
964 	/**
965 	 * Obtiene el país que se encuentra en el asunto del certificado
966 	 * 
967 	 * @return País
968 	 */
969 	public String getCountry () {
970 		
971 		logger.debug ("[Certificate.getCountry]::Entrada");
972 		
973 		return getElementSubject(BCStyle.C);
974 	}
975 	
976 	/**
977 	 * Obtiene la cadena de texto contenida en el Subject del certificado
978 	 * 
979 	 * @return Name del Distinguished Name que forma el Subject del certificado
980 	 */
981 	public String getSubjectDN () {
982 		return this.certificate.getSubjectDN().getName();
983 	}
984 	
985 	/**
986 	 * Obtiene la cadena de texto contenida en el Issuer del certificado
987 	 * 
988 	 * @return Name del Distinguished Name que forma el Issuer del certificado
989 	 */
990 	public String getIssuerDN () {
991 		return this.certificate.getIssuerDN().getName();
992 	}
993 	
994 	/**
995 	 * Obtiene el common name del Issuer del certificado
996 	 * 
997 	 * @return Common name del Issuer del certificado
998 	 */
999 	public String getIssuerCommonName () {
1000 		
1001 		logger.debug ("[Certificate.getIssuerCommonName]::Entrada");
1002 		
1003 		String dn = this.certificate.getIssuerDN().getName();
1004 		StringTokenizer st = new StringTokenizer(dn, ",");
1005 		while(st.hasMoreTokens()) {
1006 			String token = st.nextToken();
1007 			if (token.startsWith("CN=")) {
1008 				return token.substring(3);
1009 			}
1010 		}
1011 		
1012 		return null;
1013 	}
1014 	
1015 	/**
1016 	 * Obtiene una lista que representa el contenido de la extensión Subject Alternative 
1017 	 * Name (Nombre Alternativo del Sujeto). Cada elemento es de tipo 
1018 	 * {@link es.accv.arangi.base.util.AlternativeNameElement AlternativeNameElement} 
1019 	 * 
1020 	 * @return Representación del Subject Alternative Name
1021 	 * @throws CertificateFieldException Error leyendo el certificado
1022 	 */
1023 	public List getSubjectAlternativeName() throws CertificateFieldException {
1024 		
1025 		logger.debug ("[Certificate.getSubjectAlternativeName]::Entrada");
1026 		
1027 		byte[] extVal = certificate.getExtensionValue(Extension.subjectAlternativeName.getId());
1028 
1029 		try {
1030 			return getAlternativeNames(extVal);
1031 		} catch (CertificateParsingException e) {
1032 			logger.info("[Certificate.getSubjectAlternativeNames]::Error leyendo la extensión SubjectAlternativeName", e);
1033 			throw new CertificateFieldException ("Error leyendo la extensión SubjectAlternativeName", e);
1034 		}
1035 	}
1036 	
1037 	/**
1038 	 * Obtiene el SAN en formato de texto 
1039 	 * 
1040 	 * @return Representación del Subject Alternative Name
1041 	 * @throws CertificateFieldException Error leyendo el certificado
1042 	 */
1043 	public String getSubjectAlternativeNameString() throws CertificateFieldException {
1044 		
1045 		logger.debug ("[Certificate.getSubjectAlternativeNameString]::Entrada");
1046 		
1047 		List<AlternativeNameElement> elementos = getSubjectAlternativeName();
1048 		StringBuffer sb = new StringBuffer("");
1049 		int i=0;
1050 		for (AlternativeNameElement elemento : elementos) {
1051 			switch (elemento.getType()) {
1052 				case GeneralName.ediPartyName:
1053 					break;
1054 				case GeneralName.x400Address:
1055 					break;
1056 				case GeneralName.otherName:
1057 					break;
1058 				case GeneralName.directoryName:
1059 					if (i>0) { sb.append(","); }
1060 					sb.append("directoryName=");
1061 					TreeMap<String,String> dn = (TreeMap<String,String>) elemento.getValue();
1062 					int campos = 0;
1063 					StringBuffer directoryName = new StringBuffer("");
1064 					for(String key : dn.keySet()) {
1065 						if (campos > 0) {directoryName.append(",");}
1066 						directoryName.append("OID." + key + "=" + dn.get(key));
1067 						campos++;
1068 					}
1069 					sb.append(LDAPDN.escapeRDN(directoryName.toString()));
1070 					i++;
1071 					break;
1072 				case GeneralName.dNSName:
1073 					if (i>0) { sb.append(","); }
1074 					sb.append("dNSName=" + elemento.getValue());
1075 					i++;
1076 					break;
1077 				case GeneralName.rfc822Name:
1078 					if (i>0) { sb.append(","); }
1079 					sb.append("rfc822Name=" + elemento.getValue());
1080 					i++;
1081 					break;
1082 				case GeneralName.uniformResourceIdentifier:
1083 					break;
1084 				case GeneralName.registeredID:
1085 					break;
1086 				case GeneralName.iPAddress:
1087 					break;
1088 			}
1089 
1090 		}
1091 		
1092 		return sb.toString();
1093 		
1094 	}
1095 
1096 	/**
1097 	 * Busca un elemento dentro de la extensión Subject Alternative Name. Normalmente
1098 	 * el vector sólo contendrá el elemento que estamos buscando.<br><br>
1099 	 * Por ejemplo:<br>
1100 	 * <code>
1101 	 * 	(String) certificate.getSubjectAlternativeNameElement("0.9.2342.19200300.100.1.1").get(0)
1102 	 * </code>
1103 	 * 
1104 	 * @param oid OID del elemento a Buscar
1105 	 * @return Valor del elemento
1106 	 * @throws CertificateFieldException Error leyendo el certificado
1107 	 */
1108 	public String getSubjectAlternativeNameElement (String oid) throws CertificateFieldException {
1109 		
1110 		logger.debug ("[Certificate.getSubjectAlternativeNameElement]::Entrada::" + oid);
1111 		
1112 		String[] resultado = getSubjectAlternativeNameElements (oid);
1113 		if (resultado.length == 0) {
1114 			return null;
1115 		}
1116 		
1117 		return resultado[0];
1118 	}
1119 	
1120 	/**
1121 	 * Busca elementos dentro de la extensión Subject Alternative Name. <br><br>
1122 	 * Por ejemplo:<br>
1123 	 * <code>
1124 	 * 	(String) certificate.getSubjectAlternativeNameElements("0.9.2342.19200300.100.1.1")
1125 	 * </code>
1126 	 * 
1127 	 * @param oid OID del elemento a Buscar
1128 	 * @return Valor del elemento
1129 	 * @throws CertificateFieldException Error leyendo el certificado
1130 	 */
1131 	public String[] getSubjectAlternativeNameElements (String oid) throws CertificateFieldException {
1132 		
1133 		logger.debug ("[Certificate.getSubjectAlternativeNameElements]::Entrada::" + oid);
1134 		
1135 		//-- Obtener la lista
1136 		List lNames = getSubjectAlternativeName();
1137 		
1138 		//-- Iterar
1139 		List<String> resultado = new ArrayList<String>();
1140 		for (Iterator iterator = lNames.iterator(); iterator.hasNext();) {
1141 			AlternativeNameElement element = (AlternativeNameElement) iterator.next();
1142 			if (element.getValue() instanceof Map) {
1143 				Map<String,String> mapElement = (Map<String,String>) element.getValue();
1144 				if (mapElement.containsKey(oid)) {
1145 					logger.debug ("[Certificate.getSubjectAlternativeNameElement]::Encontrado el elemento::" + mapElement.get(oid));
1146 					resultado.add(mapElement.get(oid));
1147 				}
1148 			}
1149 		}
1150 		
1151 		return resultado.toArray(new String[0]);
1152 	}
1153 	
1154 	/**
1155 	 * Busca en el Subject Alternative Name elementos del tipo indicado. <br><br>
1156 	 * Por ejemplo:<br>
1157 	 * <code>
1158 	 * 	certificate.getSubjectAlternativeNameElements(GeneralName.dNSName);
1159 	 * </code>
1160 	 * 
1161 	 * @param type Tipo de elemento dentro del SAN
1162 	 * @return Lista de elementos
1163 	 * @throws CertificateFieldException Error leyendo el certificado
1164 	 */
1165 	public List<AlternativeNameElement> getSubjectAlternativeNameElements (int type) throws CertificateFieldException {
1166 		
1167 		logger.debug ("[Certificate.getSubjectAlternativeNameElements]::Entrada::" + type);
1168 		
1169 		//-- Obtener la lista
1170 		List lNames = getSubjectAlternativeName();
1171 		
1172 		//-- Iterar
1173 		List<AlternativeNameElement> resultado = new ArrayList<AlternativeNameElement>();
1174 		for (Iterator iterator = lNames.iterator(); iterator.hasNext();) {
1175 			AlternativeNameElement element = (AlternativeNameElement) iterator.next();
1176 			if (element.getType() == type) {
1177 				logger.debug ("[Certificate.getSubjectAlternativeNameElement]::Encontrado el elemento para el tipo " + type);
1178 				resultado.add(element);
1179 			}
1180 		}
1181 		
1182 		return resultado;
1183 	}
1184 	
1185 	/**
1186 	 * Obtiene una lista que representa el contenido de la extensión Issuer Alternative 
1187 	 * Name (Nombre Alternativo del Emisor). Cada elemento es de tipo 
1188 	 * {@link es.accv.arangi.base.util.AlternativeNameElement AlternativeNameElement} 
1189 	 * 
1190 	 * @return Representación del Issuer Alternative Name
1191 	 * @throws CertificateFieldException Error leyendo el certificado
1192 	 */
1193 	public List getIssuerAlternativeName() throws CertificateFieldException {
1194 		
1195 		logger.debug ("[Certificate.getIssuerAlternativeNames]::Entrada");
1196 		
1197 		byte[] extVal = certificate.getExtensionValue(Extension.issuerAlternativeName.getId());
1198 
1199 		try {
1200 			return getAlternativeNames(extVal);
1201 		} catch (CertificateParsingException e) {
1202 			logger.info("[Certificate.getIssuerAlternativeNames]::Error leyendo la extensión IssuerAlternativeName", e);
1203 			throw new CertificateFieldException ("Error leyendo la extensión IssuerAlternativeName", e);
1204 		}
1205 	}
1206 
1207 	/**
1208 	 * Busca un elemento dentro de la extensión Issuer Alternative Name 
1209 	 * 
1210 	 * @param oid OID del elemento a Buscar
1211 	 * @return Vector con la información del elemento
1212 	 * @throws CertificateFieldException Error leyendo el certificado
1213 	 */
1214 	public Vector getIssuerAlternativeNameElement (String oid) throws CertificateFieldException {
1215 		
1216 		logger.debug ("[Certificate.getIssuerAlternativeNameElement]::Entrada::" + oid);
1217 		
1218 		//-- Obtener la lista
1219 		List lNames = getIssuerAlternativeName();
1220 		
1221 		//-- Iterar
1222 		for (Iterator iterator = lNames.iterator(); iterator.hasNext();) {
1223 			AlternativeNameElement element = (AlternativeNameElement) iterator.next();
1224 			if (element.getValue() instanceof Map) {
1225 				Map mapElement = (Map) element.getValue();
1226 				if (mapElement.containsKey(oid)) {
1227 					logger.debug ("[Certificate.getIssuerAlternativeNameElement]::Encontrado el elemento::" + (Vector) mapElement.get(oid));
1228 					return (Vector) mapElement.get(oid);
1229 				}
1230 			}
1231 		}
1232 		
1233 		logger.debug ("[Certificate.getIssuerAlternativeNameElement]::No se ha encontrado el elemento para el oid " + oid);
1234 		return null;
1235 	}
1236 	
1237 	/**
1238 	 * Método que devuelve el Número de Serie del certificado (Hexadecimal)
1239 	 * 
1240 	 * @return Número de Serie del certificado.
1241 	 * 
1242 	 */
1243 	public String getSerialNumber() {
1244 
1245 		logger.debug ("[Certificate.getSerialNumber]::Entrada");
1246 		
1247 		return certificate.getSerialNumber().toString(16).toUpperCase();
1248 	}
1249 	
1250 	/**
1251 	 * Método que devuelve el Número de Serie del certificado (BigInteger)
1252 	 * 
1253 	 * @return Número de Serie del certificado.
1254 	 * 
1255 	 */
1256 	public BigInteger getSerialNumberBigInteger() {
1257 
1258 		logger.debug ("[Certificate.getSerialNumberBigInteger]::Entrada");
1259 		
1260 		return certificate.getSerialNumber();
1261 	}
1262 	
1263 	/**
1264 	 * Obtiene el issuer and serial number. En algunos casos se utiliza este
1265 	 * valor para identificar el certificado en lugar del subject key
1266 	 * identifier.
1267 	 * 
1268 	 * @return Issuer and serial number
1269 	 * @throws CertificateFieldException No se ha podido leer correctamente la 
1270 	 * 	información del certificado
1271 	 */
1272 	public IssuerAndSerialNumber getIssuerAndSerialNumber() throws CertificateFieldException {
1273 		
1274 		logger.debug ("[Certificate.getIssuerAndSerialNumber]::Entrada");
1275 		
1276 		try {
1277 	        ASN1InputStream inputStreamTbsCertificate = new ASN1InputStream(new ByteArrayInputStream(toX509Certificate().getTBSCertificate()));
1278 	        ASN1Sequence seqAux = (ASN1Sequence)inputStreamTbsCertificate.readObject();
1279 	        ASN1Primitive tbsCertificateDER = (ASN1Primitive)seqAux.getObjectAt(seqAux.getObjectAt(0) instanceof DERTaggedObject ? 3 : 2);
1280 			return new IssuerAndSerialNumber(X500Name.getInstance((ASN1Sequence)tbsCertificateDER),
1281 			   		toX509Certificate().getSerialNumber());
1282 		} catch (CertificateEncodingException e) {
1283 			logger.info("[Certificate.toDER]::Error obteniendo la información del certificado en formato DER", e);
1284 			throw new CertificateFieldException ("Error obteniendo la información del certificado en formato DER", e);
1285 		} catch (IOException e) {
1286 			logger.info("[Certificate.toDER]::Error leyendo la información del certificado en formato DER", e);
1287 			throw new CertificateFieldException ("Error leyendo la información del certificado en formato DER", e);
1288 		} 
1289 	}
1290 
1291 	/**
1292 	 * Obtiene la clave pública asociada al certificado
1293 	 * 
1294 	 * @return Clave pública del certificado
1295 	 */
1296 	public PublicKey getPublicKey () {
1297 		
1298 		logger.debug ("[Certificate.getPublicKey]::Entrada");
1299 		
1300 		return certificate.getPublicKey();
1301 	}
1302 	
1303 	/**
1304 	 * Devuelve el certificado en formato X509Certificate
1305 	 * 
1306 	 * @return X509 Certificate
1307 	 */
1308 	public X509Certificate toX509Certificate () {
1309 		return certificate;
1310 	}
1311 	
1312 	/**
1313 	 * Devuelve el certificado en formato DER
1314 	 * 
1315 	 * @return Certificado en formato DER
1316 	 * @throws NormalizeCertificateException No se ha podido codificar el certificado en 
1317 	 * 	formato DER
1318 	 */
1319 	public byte[] toDER () throws NormalizeCertificateException {
1320 		try {
1321 			return certificate.getEncoded();
1322 		} catch (CertificateEncodingException e) {
1323 			logger.info("[Certificate.toDER]::Error codificando el certificado en formato DER", e);
1324 			throw new NormalizeCertificateException ("Error codificando el certificado en formato DER", e);
1325 		}
1326 	}
1327 	
1328 	/**
1329 	 * Obtiene la estructura del certificado en un objeto X509CertificateHolderç
1330 	 * de Bouncy Castle.
1331 	 * 
1332 	 * @return X509CertificateHolder
1333 	 */
1334 	public X509CertificateHolder toX509CertificateHolder () {
1335 		return new X509CertificateHolder(asn1Certificate);
1336 	}
1337 	
1338 	/**
1339 	 * Devuelve el certificado en formato PEM
1340 	 * 
1341 	 * @return Certificado en formato PEM
1342 	 * @throws NormalizeCertificateException No se ha podido codificar el certificado en 
1343 	 * 	formato DER antes de pasarlo a PEM
1344 	 */
1345 	public String toPEM () throws NormalizeCertificateException {
1346 		
1347 		return "-----BEGIN CERTIFICATE-----\n" + Util.encodeBase64(toDER()) + 
1348 			"\n-----END CERTIFICATE-----";
1349 	}
1350 	
1351 	/**
1352 	 * Crea un fichero PKCS#7 en el que almacena el certificado y su cadena de confianza.
1353 	 * 
1354 	 * @param chain Cadena de confianza. Si se pasa un valor nulo sólo se almacenará el
1355 	 * 	certificado.
1356 	 * @return Fichero PKCS#7 en formato DER
1357 	 * @throws SignatureException Errores creando el almacén PKCS#7
1358 	 */
1359     public byte[] toPKCS7(Certificate[] chain) throws SignatureException {
1360 
1361     	logger.debug("[Certificate.toPKCS7]::Entrada::" + (chain==null?"null":chain.length));
1362     	
1363     	//-- Objeto PKCS#7 
1364     	CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
1365     	
1366     	//-- Construir lista de certificados
1367     	X509Certificate certificate = toX509Certificate();
1368     	List<X509Certificate> certList = new ArrayList<X509Certificate>();
1369     	certList.add(certificate);
1370     	if (chain != null) {
1371 	    	for (int i = 0; i < chain.length; i++) {
1372 				certList.add(chain[i].toX509Certificate());
1373 			}
1374     	}
1375     	
1376     	//-- Unirlo todo y devolver en formato DER
1377     	try {
1378     		gen.addCertificates(new JcaCertStore(certList));
1379     		CMSProcessableByteArray process = new CMSProcessableByteArray(null); //no hay firmas
1380     		CMSSignedData data = gen.generate(process);
1381     		ContentInfo contentInfo = data.toASN1Structure();
1382     		return contentInfo.getEncoded(ASN1Encoding.DER);
1383     	} catch (CMSException e) {
1384 			logger.info ("[Certificate.toPKCS7]::El certificado no puede ser almacenado en formato PKCS#7", e);
1385 			throw new SignatureException ("El certificado no puede ser almacenado en formato PKCS#7", e);
1386 		} catch (IOException e) {
1387 			logger.info ("[Certificate.toPKCS7]::Excepción de entrada/salida", e);
1388 			throw new SignatureException ("Excepción de entrada/salida", e);
1389 		} catch (CertificateEncodingException e) {
1390 			logger.info ("[Certificate.toPKCS7]::El certificado no puede ser almacenado", e);
1391 			throw new SignatureException ("El certificado no puede ser almacenado", e);
1392 		} 
1393 
1394     }    
1395     
1396 	/**
1397 	 * Guarda el certificado en formato DER en el fichero que se pasa como parámetro
1398 	 * 
1399 	 * @param file Fichero donde se guardará el certificado
1400 	 * @throws Exception No se ha podido guardar el fichero
1401 	 * @throws NormalizeCertificateException No se ha podido codificar el certificado en 
1402 	 * 	formato DER
1403 	 */
1404 	public void save (File file) throws NormalizeCertificateException, Exception {
1405 		Util.saveFile(file, toDER());
1406 	}
1407 	
1408 	/**
1409 	 * Guarda el certificado en formato PEM en el fichero que se pasa como parámetro
1410 	 * 
1411 	 * @param file Fichero donde se guardará el certificado
1412 	 * @throws Exception No se ha podido guardar el fichero
1413 	 * @throws NormalizeCertificateException No se ha podido codificar el certificado en 
1414 	 * 	formato DER antes de pasarlo a PEM
1415 	 */
1416 	public void saveToPEM (File file) throws NormalizeCertificateException, Exception {
1417 		Util.saveFile(file, toPEM().getBytes());
1418 	}
1419 	
1420 	/**
1421 	 * Devuelve en texto la información más importante del certificado.
1422 	 * 
1423 	 * @return Información del certificado
1424 	 */
1425 	public String toString () {
1426 		return certificate.toString();
1427 	}
1428 	
1429 	//-- Métodos estáticos
1430 	
1431 	/**
1432 	 * Normaliza los certificados de acuerdo al proveedor criptográfico de Arangi.
1433 	 * 
1434 	 * @param originalCert Certificado a normalizar
1435 	 * @return X509Certificate Certificado normalizado de acuerdo al proveedor criptográfico 
1436 	 * de Arangi
1437 	 * 
1438 	 * @throws Exception Error durante la normalización
1439 	 */
1440 	public static X509Certificate normalize (X509Certificate originalCert) throws NormalizeCertificateException {
1441 		
1442 		byte[] bytes;
1443 		try {
1444 			bytes = originalCert.getEncoded();
1445 		} catch (CertificateEncodingException e) {
1446 			logger.info ("[Certificate.normalize]::Error de codificación del certificado", e);
1447 			throw new NormalizeCertificateException ("Error de codificación del certificado", e);
1448 		}
1449 		
1450 		ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
1451 		CertificateFactory cf;
1452 		try {
1453 			cf = CertificateFactory.getInstance("X.509", CRYPTOGRAPHIC_PROVIDER);
1454 		} catch (CertificateException e) {
1455 			logger.info ("[Certificate.normalize]::El tipo del certificado no está disponible para el proveedor criptográfico de Arangi: " + CRYPTOGRAPHIC_PROVIDER, e);
1456 			throw new NormalizeCertificateException ("El tipo del certificado no está disponible para el proveedor criptográfico de Arangi: " + CRYPTOGRAPHIC_PROVIDER, e);
1457 		} 
1458 		
1459 		X509Certificate normalizedCertificate;
1460 		try {
1461 			normalizedCertificate = (X509Certificate) cf.generateCertificate(bais);
1462 		} catch (CertificateException e) {
1463 			logger.info ("[Certificate.normalize]::Error generando el certificado", e);
1464 			throw new NormalizeCertificateException ("Error generando el certificado", e);
1465 		}
1466 		try {
1467 			bais.close();
1468 		} catch (IOException e) {}
1469 		
1470 		return normalizedCertificate;
1471 		
1472 	}
1473 	
1474 	/**
1475 	 * Método estático que obtiene el Issuer Key Identifier (IKI) a partir de un certificado
1476 	 * X.509.
1477 	 * 
1478 	 * @param certificate Certificado X.509
1479 	 * @return Issuer Key Identifier o nulo si éste no se pudo obtener del certificado
1480 	 */
1481 	public static String getIssuerKeyIdentifier(X509Certificate certificate)  {
1482 		
1483 		byte[] extension = certificate.getExtensionValue(Extension.authorityKeyIdentifier.getId());
1484 		if (extension == null) {
1485 			return null;
1486 		}
1487 	
1488 		ASN1InputStream is1 = null, is2 = null;
1489 		try {
1490 			is1 = new ASN1InputStream(extension);
1491 			byte[] authBytes = ((ASN1OctetString)is1.readObject()).getOctets();
1492 			is2 = new ASN1InputStream(authBytes);
1493 			AuthorityKeyIdentifier aki = AuthorityKeyIdentifier.getInstance(is2.readObject());
1494 			return Util.encodeBase64(aki.getKeyIdentifier());
1495 		} catch (Exception e) {
1496 			logger.debug("[Certificate.getIssuerKeyIdentifier]::No es posible obtener el IKI del certificado: " + certificate.getSubjectDN(), e);
1497 			return null;
1498 		} finally {
1499 			if (is1 != null) { try { is1.close(); } catch (IOException e) { } }
1500 			if (is2 != null) { try { is2.close(); } catch (IOException e) { } }
1501 		}
1502 	}
1503 
1504 	/**
1505 	 * Método estático que obtiene el Subject Key Identifier (SKI) a partir de un certificado
1506 	 * X.509.
1507 	 * 
1508 	 * @param certificate X.509 Certificate
1509 	 * @return Subject Key Identifier o nulo si éste no se pudo obtener del certificado
1510 	 */
1511 	public static String getSubjectKeyIdentifier(X509Certificate certificate) { 
1512 		
1513 		byte[] extension = certificate.getExtensionValue(Extension.subjectKeyIdentifier.getId());
1514 		if (extension == null) {
1515 			return null;
1516 		}
1517 		
1518 		ASN1InputStream is1 = null, is2 = null;
1519 		try {
1520 			is1 = new ASN1InputStream(extension);
1521 			byte[] authBytes = ((ASN1OctetString)is1.readObject()).getOctets();
1522 			is2 = new ASN1InputStream(authBytes);
1523 			SubjectKeyIdentifier ski = SubjectKeyIdentifier.getInstance(is2.readObject());
1524 			return Util.encodeBase64(ski.getKeyIdentifier());
1525 		} catch (Exception e) {
1526 			logger.debug("[Certificate.getSubjectKeyIdentifier]::No es posible obtener el SKI del certificado: " + certificate.getSubjectDN(), e);
1527 			return null;
1528 		} finally {
1529 			if (is1 != null) { try { is1.close(); } catch (IOException e) { } }
1530 			if (is2 != null) { try { is2.close(); } catch (IOException e) { } }
1531 		}
1532 	}
1533 	
1534     /**
1535      * Crea un objeto (Bouncycastle) X509Name a partir de un String con un DN. OIDs conocidos
1536      * (en orden) son:
1537      * <code> EmailAddress, UID, CN, SN (SerialNumber), GivenName, Initials, SurName, T, OU,
1538      * O, L, ST, DC, C </code>
1539      * 
1540      * @param dn String que contiene un DN que puede ser transformado en un X509Name. El String
1541      *          DN tiene el formato "CN=zz,OU=yy,O=foo,C=SE". OIDs desconocidos en el String
1542      *          se añadirán al final del array de OIDs
1543      * 
1544      * @return X509Name o null si el parámetro es nulo
1545      */
1546     public static X500Name stringToBcX500Name(String dn) {
1547 
1548       // log.debug(">stringToBcX509Name: " + dn);
1549       if (dn == null)
1550         return null;
1551 
1552       List<RDN> lRDNs = new ArrayList<RDN>();
1553       StringTokenizer st = new StringTokenizer(dn, ",");
1554 
1555       while (st.hasMoreTokens()) {
1556         // This is a pair (CN=xx)
1557         String pair = st.nextToken();
1558         int ix = pair.indexOf("=");
1559 
1560         if (ix != -1) {
1561           String key = pair.substring(0, ix).toLowerCase();
1562           String val = pair.substring(ix + 1);
1563 
1564           // -- First search the OID by name in declared OID's
1565           ASN1ObjectIdentifier oid = oids.get(key.toLowerCase());
1566 
1567           // -- If isn't declared, we try to create it
1568           if (oid == null) {
1569             oid = new ASN1ObjectIdentifier(key);
1570           }
1571 
1572           RDN rdn = new RDN(oid, new DERUTF8String(val));
1573           lRDNs.add(rdn);
1574 
1575         } else {
1576           logger.info("[Certificate.stringToBcX509Name]:: Algún par OID=valor no es correcto: " + dn);
1577         }
1578       }
1579 
1580       return getOrderedX500Name(new X500Name(lRDNs.toArray(new RDN[0])), getDefaultX500FieldOrder());
1581     } 
1582     
1583     /**
1584      * Genera un certificado autofirmado con los parámetros que se le pasan. El periodo de
1585      * validez comienza en el instante actual.
1586      *
1587      * @param dn DN del emisor/issuer (es mismo que el del asunto/subject) 
1588      * @param validity Días de validez
1589      * @param policyId String con la política o nulo
1590      * @param privKey Clave privada con la que se firmará el certificado
1591      * @param pubKey Clave pública
1592      * @param isCA Si cierto se marcará el certificado como de una autoridad de certificación
1593      *
1594      * @return X509Certificate auto firmado
1595      * @throws NoSuchAlgorithmException No existe el algoritmo SHA-1 Pseudo-Random Number 
1596      * 	Generation, necesario para obtener el número de serie del certificado
1597      * @throws SignatureException Error firmando el certificado
1598      * @throws IllegalStateException 
1599      * @throws InvalidKeyException La clave privada no es válida
1600      * @throws CertificateEncodingException Error codificando el nuevo certificado
1601      */
1602     public static X509Certificate generateSelfCertificate(String dn, long validity, String policyId,
1603         PrivateKey privKey, PublicKey pubKey, boolean isCA) throws NoSuchAlgorithmException, CertificateEncodingException, InvalidKeyException, IllegalStateException, SignatureException
1604     {
1605     	return generateSelfCertificate(dn, validity, policyId, privKey, pubKey, isCA, ArangiObject.DEFAULT_SIGNING_ALGORITHM);
1606     }
1607     
1608     /**
1609      * Genera un certificado autofirmado con los parámetros que se le pasan. El periodo de
1610      * validez comienza en el instante actual.
1611      *
1612      * @param dn DN del emisor/issuer (es mismo que el del asunto/subject) 
1613      * @param validity Días de validez
1614      * @param policyId String con la política o nulo
1615      * @param privKey Clave privada con la que se firmará el certificado
1616      * @param pubKey Clave pública
1617      * @param isCA Si cierto se marcará el certificado como de una autoridad de certificación
1618      * @param signatureAlgorithm Algoritmo de la firma del certificado
1619      *
1620      * @return X509Certificate auto firmado
1621      * @throws NoSuchAlgorithmException No existe el algoritmo SHA-1 Pseudo-Random Number 
1622      * 	Generation, necesario para obtener el número de serie del certificado
1623      * @throws CertificateEncodingException Error codificando el nuevo certificado
1624      */
1625     public static X509Certificate generateSelfCertificate(String dn, long validity, String policyId,
1626         PrivateKey privKey, PublicKey pubKey, boolean isCA, String signatureAlgorithm) throws NoSuchAlgorithmException, CertificateEncodingException {
1627     	
1628         // Create self signed certificate
1629         Date firstDate = new Date();
1630 
1631         // Set back startdate ten minutes to avoid some problems with wrongly set clocks.
1632         firstDate.setTime(firstDate.getTime() - (10 * 60 * 1000));
1633 
1634         Date lastDate = new Date();
1635 
1636         // Serialnumber is random bits, where random generator is initialized with Date.getTime() when this
1637         // bean is created.
1638         byte[] serno = new byte[8];
1639         SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
1640         random.setSeed((new Date().getTime()));
1641         random.nextBytes(serno);
1642         
1643        // validity in days = validity*24*60*60*1000 milliseconds
1644         lastDate.setTime(lastDate.getTime() + (validity * (24 * 60 * 60 * 1000)));
1645         
1646         SubjectPublicKeyInfo spki = SubjectPublicKeyInfo.getInstance(pubKey.getEncoded());
1647         
1648         X509v3CertificateBuilder certgen = new X509v3CertificateBuilder(
1649         		stringToBcX500Name(dn),
1650         		new java.math.BigInteger(serno),
1651         		firstDate,
1652         		lastDate,
1653         		stringToBcX500Name(dn),
1654         		spki);
1655 
1656         // Basic constranits is always critical and MUST be present at-least in CA-certificates.
1657         BasicConstraints bc = new BasicConstraints(isCA);
1658         try {
1659 			certgen.addExtension(Extension.basicConstraints, true, bc);
1660 		} catch (CertIOException e) {
1661 			logger.info("[Certificate.generateSelfCertificate]:: No se puede añadir la extensión basicConstraints", e);
1662 			throw new CertificateEncodingException ("No se puede añadir la extensión basicConstraints", e);
1663 		}
1664 
1665         // Put critical KeyUsage in CA-certificates
1666         if (isCA) {
1667             int keyusage = KeyUsage.keyCertSign + KeyUsage.cRLSign;
1668             KeyUsage ku = new KeyUsage(keyusage);
1669             try {
1670 				certgen.addExtension(Extension.keyUsage, true, ku);
1671 			} catch (CertIOException e) {
1672 				logger.info("[Certificate.generateSelfCertificate]:: No se puede añadir la extensión keyusage", e);
1673 				throw new CertificateEncodingException ("No se puede añadir la extensión keyusage", e);
1674 			}
1675         }
1676 
1677         // Subject and Authority key identifier is always non-critical and MUST be present for certificates to verify in Mozilla.
1678         try {
1679             if (isCA) {
1680                 SubjectKeyIdentifier ski = new SubjectKeyIdentifier(spki.getEncoded(ASN1Encoding.DER));
1681                 AuthorityKeyIdentifier aki = new AuthorityKeyIdentifier(spki.getEncoded(ASN1Encoding.DER));
1682 
1683                 certgen.addExtension(Extension.subjectKeyIdentifier, false, ski);
1684                 certgen.addExtension(Extension.authorityKeyIdentifier, false, aki);
1685             }
1686         } catch (IOException e) { // do nothing
1687         }
1688 
1689         // CertificatePolicies extension if supplied policy ID, always non-critical
1690         if (policyId != null) {
1691             PolicyInformation pi = new PolicyInformation(new ASN1ObjectIdentifier(policyId));
1692             DERSequence seq = new DERSequence(pi);
1693             try {
1694 				certgen.addExtension(Extension.certificatePolicies, false, seq);
1695 			} catch (CertIOException e) {
1696 				logger.debug("[Certificate.generateSelfCertificate]:: No se puede añadir la extensión certificatePolicies", e);
1697 			}
1698         }
1699 
1700 		try {
1701 			ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider(CRYPTOGRAPHIC_PROVIDER_NAME).build(privKey);
1702 	        return Util.getCertificate(certgen.build(sha1Signer));
1703 		} catch (OperatorCreationException e) {
1704 			logger.info("[Certificate.generateSelfCertificate]:: No se puede construir el nuevo certificado", e);
1705 			throw new CertificateEncodingException ("No se puede construir el nuevo certificado", e);
1706 		} catch (CertificateException e) {
1707 			logger.info("[Certificate.generateSelfCertificate]:: No se puede parsear la estructura del nuevo certificado", e);
1708 			throw new CertificateEncodingException ("No se puede parsear la estructura del nuevo certificado", e);
1709 		}
1710     } 
1711     
1712     /**
1713      * Devolverá cierto si el certificado contiene la extensión "Comprobación 
1714      * de no revocación". Esta extensión se suele utilizar en certificados de OCSP.
1715      * 
1716      * @return Cierto si el certificado contiene la extensión "Comprobación 
1717      * 	de no revocación". Falso en caso contrario.
1718      */
1719     public boolean hasNoRevocationCheck () {
1720     	logger.debug("[Certificate.hasNoRevocationCheck]::Entrada");
1721     	boolean result = certificate.getExtensionValue(OCSPObjectIdentifiers.id_pkix_ocsp_nocheck.getId()) != null;
1722     	logger.debug("[Certificate.hasNoRevocationCheck]::Resultado: " + result);
1723     	
1724     	return result;
1725     }
1726 
1727     /**
1728      * Valida el certificado a través de servicios de validación como, por ejemplo, 
1729      * &#64;Firma.
1730      * 
1731      * @param validationServices Lista de servicios de validación
1732      * @return Objeto que incluye el resultado y un map con los campos del certificado.
1733      * 	Si no es posible realizar la validación se devolverá null.
1734      */
1735     public CertificateValidationServiceResult validate (List<CertificateValidationService> validationServices) {
1736     	return validate (validationServices, new Date());
1737     }
1738     
1739     /**
1740      * Valida el certificado a través de servicios de validación como, por ejemplo, 
1741      * &#64;Firma.
1742      * 
1743      * @param validationServices Lista de servicios de validación
1744      * @param validationDate Fecha para la que se realiza la validación
1745      * @return Objeto que incluye el resultado y un map con los campos del certificado.
1746      */
1747     public CertificateValidationServiceResult validate (List<CertificateValidationService> validationServices, Date validationDate) {
1748     	logger.debug("[Certificate.validate]::Entrada::" + Arrays.asList(new Object[] { validationServices, validationDate } ));
1749     	
1750     	CertificateValidationServiceResult result = null;
1751     	
1752 		//-- Comprobar si está en su periodo de validez
1753 		if (getValidityPeriodBeginning().after(validationDate)) {
1754 			logger.debug ("[Certificate.validate] :: El certificado con subject DN=" + getSubjectDN().toString() + 
1755 				" no estará activo hasta " + dateFormat.format(getValidityPeriodBeginning()) + ".");
1756 			return new CertificateValidationServiceResult (ValidationResult.RESULT_CERTIFICATE_NOT_ACTIVE, null);
1757 		}
1758 		if (getValidityPeriodEnd().before(validationDate)) {
1759 			logger.debug ("[Certificate.validate] :: El certificado con subject DN=" + getSubjectDN().toString() + 
1760 				" ha caducado en " + dateFormat.format(getValidityPeriodEnd()) + ".");
1761 			return new CertificateValidationServiceResult (ValidationResult.RESULT_CERTIFICATE_NOT_ACTIVE, null);
1762 		}
1763 		
1764     	//-- Comprobar si es autofirmado
1765 		try {
1766 			if (isSelfSigned()) {
1767 				logger.debug ("[Certificate.validate] :: Certificado con subject DN=" + getSubjectDN().toString() +  
1768 						" es válido y autofirmado.");
1769 				return new CertificateValidationServiceResult (ValidationResult.RESULT_VALID, null);
1770 			}
1771 		} catch (NormalizeCertificateException e1) {
1772 			// Esta excepción ya se habrá dado en la inicialización, por lo que no se habría iniciado este objeto
1773 		}
1774 
1775     	logger.debug("[Certificate.validate] :: El certificado no ha caducado ni es autofirmado, ir a los servicios de validación a validar.");
1776     	for (CertificateValidationService service : validationServices) {
1777 			if (service != null) {
1778 				try {
1779 					result = service.validate(this, null);
1780 				} catch (Exception e) {
1781 			    	logger.info("[Certificate.validate]::No se ha podido validar en " + service, e);
1782 			    	continue;
1783 				} 
1784 				if (result.getResult() == ValidationResult.RESULT_VALID) {
1785 					break;
1786 				}
1787 			}
1788 		}
1789     	
1790     	//-- Si el certificado está revocado comparar la fecha de revocación con la fecha de comprobación
1791     	if (result != null && result.getResult() == ValidationResult.RESULT_CERTIFICATE_REVOKED) {
1792     		if (result.getRevocationDate() != null && result.getRevocationDate().after(validationDate)) {
1793     			logger.debug("[Certificate.validate] :: Aunque el certificado está revocado no lo estaba en la fecha de la validación. Fecha de revocación: " + result.getRevocationDate());
1794     			result.setResult(ValidationResult.RESULT_VALID);
1795     		}
1796     	}
1797     	
1798     	//-- Si no se ha podido validar se devuelve el código adecuado
1799     	if (result == null) {
1800 			logger.debug("[Certificate.validate] :: No se ha podido validar el certificado");
1801     		result = new CertificateValidationServiceResult(ValidationResult.RESULT_CERTIFICATE_CANNOT_BE_VALIDATED, null);
1802     	}
1803     	
1804        	logger.debug("[Certificate.validate]::resultado: " + result.getResult());
1805     	return result;
1806     }
1807     
1808     /**
1809      * Obtiene información del certificado mediante llamadas a servicios externos.
1810      * 
1811      * @param dataServices Servicios de obtención de información de certificados
1812      * @return Información o null si no es posible obtenerla
1813      */
1814     public Map<String,String> getData (List<CertificateDataService> dataServices) {
1815     	logger.debug("[Certificate.getData]::Entrada::" + Arrays.asList(new Object[] { dataServices } ));
1816     	
1817     	for(CertificateDataService service : dataServices) {
1818     		try {
1819 				Map<String,String> data = service.getData(this, null);
1820 				if (data != null) {
1821 					logger.debug("[Certificate.getData]::Obtenidos los campos: " + data);
1822 					return data;
1823 				}
1824 			} catch (Exception e) {
1825 		    	logger.info("[Certificate.getData]::No se han podido obtener los campos en " + service);
1826 			} 
1827     	}
1828     	
1829 		logger.debug("[Certificate.getData]::No se han podido obtener los campos");
1830 		return null;
1831     }
1832     
1833 	/**
1834 	 * Método que devuelve la dirección de correo electrónico del certificado
1835 	 * 
1836 	 * @return E-mail del certificado
1837 	 */
1838 	public String getCertificateEmail () {
1839 		
1840 		logger.debug ("[Certificate.getCertificateEmail]::Entrada");
1841 		
1842 		List altNames;
1843 		try {
1844 			altNames = getSubjectAlternativeName();
1845 		} catch (CertificateFieldException e) {
1846 			logger.info ("[Certificate.getCertificateEmail]::No ha sido posible obtener el e-mail", e);
1847 			return null;
1848 		}
1849 		
1850 		//-- Si no hay san no hay email
1851 		if (altNames == null || altNames.isEmpty()) {
1852 			return null;
1853 		}
1854 	
1855 		//-- Es el primer elemento del nombre alternativo
1856 		return (String) ((AlternativeNameElement) altNames.get(0)).getValue();
1857 	}
1858 	
1859 	/**
1860 	 * Método que obtiene todos los clientes OCSP que pueden validar este 
1861 	 * certificado. <br><br>
1862 	 *
1863 	 * Se devuelven los clientes OCSP que apuntan a las URLs indicadas
1864 	 * en la extensión Authority Information Access (AIA) del certificado.
1865 	 * 
1866 	 * @return Clientes OCSP para validar este certificado
1867 	 */
1868 	public OCSPClient[] getOCSPClients () {
1869 		
1870 		logger.debug ("[Certificate.getOCSPClients]::Entrada");
1871 		
1872 		List lOCSPClients = new ArrayList ();
1873 		
1874 		//-- Buscar los OCSPs en base al campo del certificado
1875 		String urlsOCSP [] = null;
1876 		try {
1877 			urlsOCSP = getOcspUrls();
1878 			for (int i = 0; i < urlsOCSP.length; i++) {
1879 				try {
1880 					lOCSPClients.add (new OCSPClient (new URL (urlsOCSP[i])));
1881 				} catch (MalformedURLException e1) {
1882 					//-- No se añade a la lista porque la URL no es válida
1883 					logger.debug("[Certificate.getOCSPClients]::La URL no es válida::" + urlsOCSP[i]);
1884 				}
1885 			}
1886 			
1887 			return (OCSPClient[]) lOCSPClients.toArray(new OCSPClient[0]);
1888 		} catch (Exception e) {
1889 			//-- No se han encontrado, devolver lista vacía
1890 			logger.debug("[Certificate.getOCSPClients]::No se han encontrado URLs para OCSP ni en " +
1891 					"un fichero validation.xml ni en el campo AIA");
1892 			return new OCSPClient [0];
1893 		}
1894 	}
1895 	
1896 	/**
1897 	 * Obtiene una respuesta OCSP de validación de este certificado. Si no se
1898 	 * puede obtener una respuesta será por alguno de estos motivos:
1899 	 * <ul>
1900 	 * 	<li>El certificado no contiene la URL de ningún servidor de OCSP. El
1901 	 * 	motivo de esta ausencia de información puede ser debido a que se trata 
1902 	 *  de un certificado autofirmado o es un certificado utilizado en la firma 
1903 	 *  de OCSPs. En cualquier otro caso, si se desea obtener una respuesta OCSP 
1904 	 *  se deberá utilizar la clase {@link es.accv.arangi.base.certificate.validation.OCSPClient OCSPClient}
1905 	 *  con la URL del servidor OCSP que valide este tipo de certificados.</li>
1906 	 * 	<li>No es posible la conexión a los servidores OCSP indicados en el
1907 	 * 	certificado o éstos no están respondiendo.</li>
1908 	 * </ul>
1909 	 * 
1910 	 * @return Respuesta OCSP o null si ésta no se puede obtener
1911 	 */
1912 	public OCSPResponse getOCSPResponse () {
1913 		
1914 		logger.debug ("[Certificate.getOCSPResponse]::Entrada");
1915 		
1916 		OCSPClient[] ocspClients = getOCSPClients();
1917 		OCSPResponse response = null;
1918 		for (int i = 0; i < ocspClients.length; i++) {
1919 			try {
1920 				response = ocspClients[i].getOCSPResponse(this);
1921 				break;
1922 			} catch (Exception e) {
1923 				logger.info("[Certificate.getOCSPResponse]::No se puede obtener respuesta OCSP de " + ocspClients[i].getURL(), e);
1924 			} 
1925 		}
1926 		
1927 		return response;		
1928 	}
1929 	
1930     @Override
1931     public boolean equals(Object obj) {
1932     	
1933     	//-- Si no son del mismo tipo no son iguales
1934     	if (!(obj instanceof Certificate)) {
1935     		return false;
1936     	}
1937     	
1938     	//-- Son iguales si tienen el mismo issuerAndSerialNumber
1939     	Certificate certificateToCompare = (Certificate) obj;
1940     	IssuerAndSerialNumber issuerSN1;
1941     	IssuerAndSerialNumber issuerSN2;
1942 		try {
1943 			issuerSN1 = certificateToCompare.getIssuerAndSerialNumber();
1944 			issuerSN2 = getIssuerAndSerialNumber();
1945 		} catch (CertificateFieldException e) {
1946 			return false;
1947 		}
1948     	
1949     	if (issuerSN1.getName().equals(issuerSN2.getName()) &&
1950     			issuerSN1.getSerialNumber().getValue().equals(issuerSN2.getSerialNumber().getValue())) {
1951     		return true;
1952     	}
1953     	
1954     	return false;
1955     }
1956     
1957 	//-- Métodos privados
1958 	
1959 	/**
1960 	 * Método que inicializa la clase
1961 	 * 
1962 	 * @throws NormalizeCertificateException No se puede normalizar el certificado
1963 	 */
1964 	private void initialize (X509Certificate certificate) throws NormalizeCertificateException {
1965 		
1966 		//-- Cargar el certificado
1967 		this.certificate = normalize (certificate);
1968 
1969 		//-- Cargar el certificado en ASN.1
1970 		try {
1971 			ASN1InputStream ais = new ASN1InputStream(certificate.getEncoded());
1972 			ASN1Primitive obj = ais.readObject();
1973 			ASN1Sequence seq = (ASN1Sequence)obj;
1974 			ais.close();
1975 			this.asn1Certificate = org.bouncycastle.asn1.x509.Certificate.getInstance(seq);
1976 		} catch (Exception e) {
1977 			logger.info("[Certificate.initialize]::No ha sido posible obtener una representación ASN.1 del certificado", e);
1978 			throw new NormalizeCertificateException ("No ha sido posible obtener una representación ASN.1 del certificado", e);
1979 		}
1980 
1981 	}
1982 
1983 	/*
1984 	 * Reune los valores de la extensión en una lista en la que cada elemento es una lista
1985 	 */
1986 	private List getAlternativeNames(byte[] extVal) throws CertificateParsingException {
1987 		List result = new ArrayList ();
1988 		if (extVal == null) {
1989 			return result;
1990 		}
1991 		try {
1992 			byte[] extnValue = DEROctetString.getInstance(ASN1Primitive.fromByteArray(extVal)).getOctets();
1993 			Enumeration it = DERSequence.getInstance(ASN1Primitive.fromByteArray(extnValue)).getObjects();
1994 			while (it.hasMoreElements()) {
1995 				GeneralName genName = GeneralName.getInstance(it.nextElement());
1996 				AlternativeNameElement element = new AlternativeNameElement ();
1997 				element.setType(genName.getTagNo());
1998 				switch (genName.getTagNo()) {
1999 					case GeneralName.ediPartyName:
2000 					case GeneralName.x400Address:
2001 					case GeneralName.otherName:
2002 						element.setValue(genName.getName().toASN1Primitive());
2003 						break;
2004 					case GeneralName.directoryName:
2005 						element.setValue(X500Name.getInstance(genName.getName()));
2006 						break;
2007 					case GeneralName.dNSName:
2008 					case GeneralName.rfc822Name:
2009 					case GeneralName.uniformResourceIdentifier:
2010 						element.setValue(((ASN1String)genName.getName()).getString());
2011 						break;
2012 					case GeneralName.registeredID:
2013 						element.setValue(ASN1ObjectIdentifier.getInstance(genName.getName()).getId());
2014 						break;
2015 					case GeneralName.iPAddress:
2016 						element.setValue(new String (DEROctetString.getInstance(genName.getName()).getOctets()));
2017 						break;
2018 					default:
2019 						throw new IOException("Bad tag number: " + genName.getTagNo());
2020 				}
2021 
2022 				result.add(element);
2023 			}
2024 		} catch (Exception e) {
2025 			throw new CertificateParsingException(e.getMessage());
2026 		}
2027 		return result;
2028 	}
2029 
2030     /*
2031      * Obtiene un vector con el DERObjectIdentifiers para los DNObjects names
2032      * 
2033      * @return
2034      */
2035     private static List<ASN1ObjectIdentifier> getDefaultX500FieldOrder(){
2036       
2037     	List<ASN1ObjectIdentifier> fieldOrder = new ArrayList<ASN1ObjectIdentifier>();
2038       
2039       for (int i = 0; i < dNObjects.length; i++) {
2040         fieldOrder.add(oids.get(dNObjects[i].toLowerCase()));
2041       }
2042       
2043       return fieldOrder;
2044       
2045     }
2046     
2047     /**
2048      * Obtiene un x500Name reordenado, si algunos campos del x500Name original no
2049      * aparecen en el parámetro 'ordering' se añadirán al final
2050      *   
2051      * @param x500Name
2052      * @param ordering, Vector de DERObjectIdentifier
2053      * @return
2054      */
2055     private static X500Name getOrderedX500Name( X500Name x500Name, List<ASN1ObjectIdentifier> ordering ){
2056       
2057       //-- Null prevent
2058       if ( ordering == null ){ ordering = new ArrayList<ASN1ObjectIdentifier>(); }
2059       
2060       //-- New order for the X509 Fields
2061       List<RDN> newRDNs  = new ArrayList<RDN>();
2062       
2063       HashMap<ASN1ObjectIdentifier,Object> ht = new HashMap<ASN1ObjectIdentifier,Object>();
2064       Iterator<ASN1ObjectIdentifier> it = ordering.iterator();
2065       
2066       logger.debug("Add ordered fields: ");
2067       //-- Add ordered fields
2068       while( it.hasNext() ) {
2069         ASN1ObjectIdentifier oid = it.next();
2070         
2071         if ( !ht.containsKey(oid) ){
2072         	List<RDN> valueList = getX500NameFields(x500Name, oid);
2073     
2074           //-- Only add the OID if has not null value
2075           if ( valueList != null ){
2076             Iterator<RDN> itVals = valueList.iterator();
2077             
2078             while( itVals.hasNext() ){
2079             	RDN value = itVals.next();
2080             	ht.put(oid, value);
2081             	newRDNs.add(value);
2082              }
2083             
2084           }
2085         }
2086       }
2087       
2088       RDN[] rDNs = x500Name.getRDNs();
2089       
2090       logger.debug("Add unespected fields to the end: ");
2091       //-- Add unespected fields to the end
2092       for ( int i=0; i<rDNs.length; i++ ) {
2093         
2094         ASN1ObjectIdentifier oid = rDNs[i].getFirst().getType();
2095 
2096         if ( !ht.containsKey(oid) ){
2097         	List<RDN> valueList = getX500NameFields(x500Name, oid);
2098     
2099           //-- Only add the OID if has not null value
2100           if ( valueList != null ){
2101             Iterator<RDN> itVals = valueList.iterator();
2102             
2103             while( itVals.hasNext() ){
2104             	RDN value = itVals.next();
2105             	ht.put(oid, value);
2106             	newRDNs.add(value);
2107             	logger.debug("added --> " + oid + " val: " + value);
2108             }
2109             
2110           }
2111         }
2112         
2113       } 
2114       
2115       //-- Create X509Name with the ordered fields
2116       X500Name orderedName = new X500Name(newRDNs.toArray(new RDN[0]));
2117       logger.debug("[getOrderedX509Name.retorna]:: " + orderedName);
2118       
2119       return orderedName;
2120       
2121     }
2122 
2123     /*
2124      * Obtiene el valor para un campo DN a partir de un X509Name, o nulo si
2125      *  el campo no existe.
2126      * 
2127      * @param name
2128      * @param id
2129      * @return
2130      */
2131     private static List<RDN> getX500NameFields( X500Name name, ASN1ObjectIdentifier id ){
2132       
2133       RDN[] rDNs = name.getRDNs();
2134       List<RDN> vRet = null;
2135       
2136 	  for (int j = 0; j < rDNs.length; j++) {
2137 	        if ( rDNs[j].getFirst().getType().equals(id)) {
2138 	            if ( vRet == null ){ vRet = new ArrayList<RDN>(); }
2139 	            vRet.add(rDNs[j]);
2140 	          }
2141 
2142 	  }
2143       
2144       return vRet;
2145       
2146     }
2147 
2148 
2149 }