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.certificate;
22  
23  import java.io.File;
24  import java.io.FileNotFoundException;
25  import java.io.InputStream;
26  import java.security.cert.X509Certificate;
27  import java.util.ArrayList;
28  import java.util.HashSet;
29  import java.util.List;
30  
31  import org.apache.log4j.Logger;
32  
33  import es.accv.arangi.base.certificate.Certificate;
34  import es.accv.arangi.base.certificate.validation.CAList;
35  import es.accv.arangi.base.exception.certificate.CertificateCANotFoundException;
36  import es.accv.arangi.base.exception.certificate.CertificateFieldException;
37  import es.accv.arangi.base.exception.certificate.NormalizeCertificateException;
38  import es.accv.arangi.base.exception.certificate.ValidationXMLException;
39  import es.accv.arangi.base.util.AlternativeNameElement;
40  import es.accv.arangi.exception.ResourceNotLoadedException;
41  import es.accv.arangi.util.ArangiUtil;
42  
43  /**
44   * Clase para el tratamiento de los certificados reconocidos de seudónimo de la ACCV, 
45   * según la política definida en la URL: 
46   * <a href="http://www.accv.es/pdf-politicas/ACCV-CP-13V2.0-c.pdf" target="politica">
47   * http://www.accv.es/pdf-politicas/ACCV-CP-13V2.0-c.pdf</a>
48   * 
49   * @author <a href="mailto:jgutierrez@accv.es">José M Gutiérrez</a>
50   */
51  public class CertificadoSeudonimo extends CertificadoACCV implements CertificadoEmpleado {
52  
53  	/*
54  	 * Logger de la clas
55  	 */
56  	static Logger logger = Logger.getLogger(CertificadoSeudonimo.class);
57  	
58  	/**
59  	 * Base del OID de la política de certificados de seudónimo en dispositivo seguro
60  	 */
61  	public static final String POLICY_IN_PKCS11_DEVICE = "1.3.6.1.4.1.8149.3.21";
62  
63  	/**
64  	 * Base del OID de la política de certificados de seudónimo en dispositivo software
65  	 */
66  	public static final String POLICY_IN_SOFTWARE_DEVICE = "1.3.6.1.4.1.8149.3.27";
67  
68  	/**
69  	 * Base del OID de la política de certificados de seudónimo en la nube
70  	 */
71  	public static final String POLICY_IN_CLOUD = "1.3.6.1.4.1.8149.3.28";
72  
73  	/**
74  	 * OID del campo con el cargo del empleado público: versión 1 de la política
75  	 */
76  	public static final String OID_CARGO_VERSION_1 = "1.3.6.1.4.1.8149.4.3.11"; 
77  	
78  	/**
79  	 * OID del campo con el seudónimo: versión 1 de la política
80  	 */
81  	public static final String OID_SEUDONIMO_VERSION_1 = "1.3.6.1.4.1.8149.4.3.4"; 
82  	
83  	/**
84  	 * OID del campo con el CIF del organismo: versión 1 de la política
85  	 */
86  	public static final String OID_CIF_ORGANISMO_VERSION_1 = "1.3.6.1.4.1.8149.4.3.3"; 
87  	
88  	/**
89  	 * OID del campo con el nombre del organismo: versión 1 de la política
90  	 */
91  	public static final String OID_NOMBRE_ORGANISMO_VERSION_1	= "1.3.6.1.4.1.8149.4.3.2"; 
92  	
93  	/**
94  	 * OID del campo con la unidad donde trabaja el propietario del seudónimo: versión 1 de la política
95  	 */
96  	public static final String OID_UNIDAD_VERSION_1	= "1.3.6.1.4.1.8149.4.3.10"; 
97  	
98  	/**
99  	 * OID del campo con el cargo del empleado público: versión 2 de la política
100 	 */
101 	public static final String OID_CARGO_VERSION_2 = "2.16.724.1.3.5.4.2.11"; 
102 	
103 	/**
104 	 * OID del campo con el seudónimo: versión 2 de la política
105 	 */
106 	public static final String OID_SEUDONIMO_VERSION_2 = "2.16.724.1.3.5.4.2.12"; 
107 	
108 	/**
109 	 * OID del campo con el CIF del organismo: versión 2 de la política
110 	 */
111 	public static final String OID_CIF_ORGANISMO_VERSION_2 = "2.16.724.1.3.5.4.2.3"; 
112 	
113 	/**
114 	 * OID del campo con el nombre del organismo: versión 2 de la política
115 	 */
116 	public static final String OID_NOMBRE_ORGANISMO_VERSION_2	= "2.16.724.1.3.5.4.2.2"; 
117 	
118 	/**
119 	 * OID del campo con la unidad donde trabaja el propietario del seudónimo: versión 2 de la política
120 	 */
121 	public static final String OID_UNIDAD_VERSION_2	= "2.16.724.1.3.5.4.2.10"; 
122 	
123 	/**
124 	 * Alias del keystore donde se guarda el certificado
125 	 */
126 	public static final String ALIAS_PKCS11 = "SEUD";
127 
128 	/*
129 	 * Lista de SKI de los certificados de CA de explotación
130 	 */
131 	private static HashSet setExplotationCACertificates = new HashSet();
132 	
133 	/*
134 	 * Lista de SKI de los certificados de CA de test
135 	 */
136 	private static HashSet setTestCACertificates = new HashSet();
137 	
138 	/**
139 	 * Constructor con un certificado X509Certificate
140 	 * 
141 	 * @param certificate Certificado en formato X.509
142 	 * @throws CertificateCANotFoundException No se ha encontrado alguno de los certificados de
143 	 * las CA que tratan este certificado en el classpath
144 	 * @throws NormalizeCertificateException El certificado no puede ser normalizado al formato
145 	 * 	reconocido por el proveedor criptográfico de Arangi o su firma no es correcta o no
146 	 * 	puede ser analizada
147 	 */
148 	public CertificadoSeudonimo(X509Certificate certificate) throws CertificateCANotFoundException, NormalizeCertificateException {
149 		super(certificate, getCAList());
150 	}
151 	
152 	/**
153 	 * Constructor con un fichero que contiene un certificado
154 	 * 
155 	 * @param fileCertificate Fichero que contiene un certificado en formato X.509
156 	 * @throws CertificateCANotFoundException No se ha encontrado alguno de los certificados de
157 	 * las CA que tratan este certificado en el classpath
158 	 * @throws NormalizeCertificateException El certificado no puede ser normalizado al formato
159 	 * 	reconocido por el proveedor criptográfico de Arangi o su firma no es correcta o no
160 	 * 	puede ser analizada
161 	 * @throws FileNotFoundException El fichero no existe
162 	 */
163 	public CertificadoSeudonimo(File fileCertificate) throws CertificateCANotFoundException, NormalizeCertificateException, FileNotFoundException {
164 		super(fileCertificate, getCAList());
165 	}
166 	
167 	/**
168 	 * Constructor con un fichero que contiene un certificado
169 	 * 
170 	 * @param isCertificate Stream de lectura a un certificado en formato X.509
171 	 * @throws CertificateCANotFoundException No se ha encontrado alguno de los certificados de
172 	 * las CA que tratan este certificado en el classpath
173 	 * @throws NormalizeCertificateException El certificado no puede ser normalizado al formato
174 	 * 	reconocido por el proveedor criptográfico de Arangi o su firma no es correcta o no
175 	 * 	puede ser analizada
176 	 */
177 	public CertificadoSeudonimo(InputStream isCertificate) throws CertificateCANotFoundException, NormalizeCertificateException {
178 		super(isCertificate, getCAList());
179 	}
180 	
181 	/**
182 	 * Constructor con un fichero que contiene un certificado
183 	 * 
184 	 * @param contenidoCertificado Contenido de un certificado en formato X.509
185 	 * @throws CertificateCANotFoundException No se ha encontrado alguno de los certificados de
186 	 * las CA que tratan este certificado en el classpath
187 	 * @throws NormalizeCertificateException El certificado no puede ser normalizado al formato
188 	 * 	reconocido por el proveedor criptográfico de Arangi o su firma no es correcta o no
189 	 * 	puede ser analizada
190 	 */
191 	public CertificadoSeudonimo(byte[] contenidoCertificado) throws CertificateCANotFoundException, NormalizeCertificateException {
192 		super(contenidoCertificado, getCAList());
193 	}
194 	
195 	//-- Métodos públicos
196 	
197 	/**
198 	 * Comprueba si el certificado es de una CA de test
199 	 * 
200 	 * @return Cierto si el certificado es de una CA de test
201 	 */
202 	public boolean isTestCertificate () {
203 		logger.debug("[CertificadoSeudonimo.isTestCertificate]::Entrada");
204 		return setTestCACertificates.contains(getIssuerKeyIdentifier());
205 	}
206 	
207 	/**
208 	 * Método que devuelve el seudónimo del titular del certificado
209 	 * 
210 	 * @return Seudónimo del titular del certificado
211 	 */
212 	public String getPseudonym () {
213 		
214 		logger.debug ("[CertificadoSeudonimo.getPseudonym]::Entrada");
215 		
216 		String result = null;
217 		try {
218 			result = getSubjectAlternativeNameElement(OID_SEUDONIMO_VERSION_1);
219 			if (result != null) {
220 				return result;
221 			} else {
222 				return getSubjectAlternativeNameElement(OID_SEUDONIMO_VERSION_2);
223 			}
224 		} catch (CertificateFieldException e) {
225 			logger.info ("[CertificadoSeudonimo.getPosition]::No se puede obtener el seudónimo", e);
226 			return null;
227 		}
228 	}
229 	
230 	/**
231 	 * Método que obtiene el valor diferenciador para este tipo
232 	 * de certificados
233 	 */
234 	public String getNRPPseudonym() {
235 		return getPseudonym();
236 	}
237 	
238 	/**
239 	 * Método que devuelve la dirección de correo electrónico del titular del certificado
240 	 * 
241 	 * @return E-mail del titular del certificado
242 	 */
243 	public String getEmail () {
244 		
245 		logger.debug ("[CertificadoSeudonimo.getEmail]::Entrada");
246 		
247 		List altNames;
248 		try {
249 			altNames = getSubjectAlternativeName();
250 		} catch (CertificateFieldException e) {
251 			logger.info ("[CertificadoSeudonimo.getEmail]::No ha sido posible obtener el e-mail", e);
252 			return null;
253 		}
254 	
255 		//-- Es el primer elemento del nombre alternativo
256 		return (String) ((AlternativeNameElement) altNames.get(0)).getValue();
257 	}
258 	
259 	/**
260 	 * Método que obtiene el cargo del Empleado Público.
261 	 * 
262 	 * @return Cargo del Empleado Público
263 	 */
264 	public String getPosition() {
265 		
266 		logger.debug ("[CertificadoSeudonimo.getPosition]::Entrada");
267 		
268 		String result = null;
269 		try {
270 			result = getSubjectAlternativeNameElement(OID_CARGO_VERSION_1);
271 			if (result != null) {
272 				return result;
273 			} else {
274 				return getSubjectAlternativeNameElement(OID_CARGO_VERSION_2);
275 			}
276 		} catch (CertificateFieldException e) {
277 				logger.info ("[CertificadoSeudonimo.getPosition]::No se puede obtener el cargo", e);
278 				return null;
279 		}
280 	}
281 	
282 	/**
283 	 * Método que obtiene el CIF de la entidad suscriptora del certificado.
284 	 * 
285 	 * @return CIF de la entidad suscriptora del certificado
286 	 */
287 	public String getEntityCIF() {
288 		
289 		logger.debug ("[CertificadoSeudonimo.getCIFEntidad]::Entrada");
290 		
291 		String result = null;
292 		try {
293 			result = getSubjectAlternativeNameElement(OID_CIF_ORGANISMO_VERSION_1);
294 			if (result != null) {
295 				return result;
296 			} else {
297 				return getSubjectAlternativeNameElement(OID_CIF_ORGANISMO_VERSION_2);
298 			}
299 		} catch (CertificateFieldException e) {
300 			logger.info ("[CertificadoSeudonimo.getEntityCIF]::No se puede obtener el nombre de la entidad suscriptora", e);
301 			return null;
302 		}
303 	}
304 	
305 	/**
306 	 * Método que obtiene el nombre de la entidad suscriptora del certificado.
307 	 * 
308 	 * @return Nombre de la entidad suscriptora del certificado
309 	 */
310 	public String getEntityName() {
311 		
312 		logger.debug ("[CertificadoSeudonimo.getEntityName]::Entrada");
313 		
314 		String result = null;
315 		try {
316 			result = getSubjectAlternativeNameElement(OID_NOMBRE_ORGANISMO_VERSION_1);
317 			if (result != null) {
318 				return result;
319 			} else {
320 				return getSubjectAlternativeNameElement(OID_NOMBRE_ORGANISMO_VERSION_2);
321 			}
322 		} catch (CertificateFieldException e) {
323 			logger.info ("[CertificadoSeudonimo.getEntityName]::No se puede obtener el nombre de la entidad suscriptora", e);
324 			return null;
325 		}
326 	}
327 	
328 	/**
329 	 * Devuelve la Unidad, dentro de la Administración, en la que está incluida el suscriptor
330 	 * del certificado.
331 	 * 
332 	 * @return Organization Unit del titular del certificado.
333 	 */
334 	public String getOrganizationalUnit() {
335 		
336 		logger.debug ("[CertificadoSeudonimo.getOrganizationalUnit]::Entrada");
337 
338 		String result = null;
339 		try {
340 			result = getSubjectAlternativeNameElement(OID_UNIDAD_VERSION_1);
341 			if (result != null) {
342 				return result;
343 			} else {
344 				return getSubjectAlternativeNameElement(OID_UNIDAD_VERSION_2);
345 			}
346 		} catch (CertificateFieldException e) {
347 			logger.info ("[CertificadoSeudonimo.getOrganizationalUnit]::No se puede obtener la unidad", e);
348 			return null;
349 		}
350 	}
351 	
352 	/**
353 	 * El certificado se encuentra en un dispositivo PKCS#11
354 	 * 
355 	 * @return Cierto si el certificado se encuentra en un dispositivo PKCS#11
356 	 */
357 	public boolean isInPkcs11Device () {
358 		logger.debug ("[CertificadoSeudonimo.isInPkcs11Device]::Entrada");
359 		
360 		for (String policyOID : getPolicyOIDs()) {
361 			if (policyOID.startsWith(POLICY_IN_PKCS11_DEVICE)) {
362 				return true;
363 			}
364 		}
365 		
366 		return false;
367 	}
368 	
369 	/**
370 	 * El certificado se encuentra en un dispositivo software (PKCS#12)
371 	 * 
372 	 * @return Cierto si el certificado se encuentra en un dispositivo software (PKCS#12)
373 	 */
374 	public boolean isInSoftwareDevice () {
375 		logger.debug ("[CertificadoSeudonimo.isInSoftwareDevice]::Entrada");
376 		
377 		for (String policyOID : getPolicyOIDs()) {
378 			if (policyOID.startsWith(POLICY_IN_SOFTWARE_DEVICE)) {
379 				return true;
380 			}
381 		}
382 		
383 		return false;
384 	}
385 	
386 	/**
387 	 * El certificado se encuentra en la nube
388 	 * 
389 	 * @return Cierto si el certificado se encuentra en la nube
390 	 */
391 	public boolean isInCloud () {
392 		logger.debug ("[CertificadoSeudonimo.isInCloud]::Entrada");
393 		
394 		for (String policyOID : getPolicyOIDs()) {
395 			if (policyOID.startsWith(POLICY_IN_CLOUD)) {
396 				return true;
397 			}
398 		}
399 		
400 		return false;
401 	}
402 	
403 	/**
404 	 * Método que indica si el certificado es válido para el cifrado de datos: NO
405 	 * 
406 	 * @return Cierto si el certificado es válido para el cifrado de datos
407 	 */
408 	public boolean isCipherCertificate() {
409 		return false;
410 	}
411 
412 	/**
413 	 * Método que indica si el certificado es válido para la firma digital:SI
414 	 * 
415 	 * @return Cierto si el certificado es válido para la firma digital
416 	 */
417 	public boolean isSigningCertificate() {
418 		return true;
419 	}
420 	
421 	/**
422 	 * Obtiene la lista de certificados de CA y raíz que conforman las posibles cadenas
423 	 * de confianza de los certificados de esta clase. 
424 	 */
425 	public static CAList getCAList() throws CertificateCANotFoundException {
426 		
427 		//-- Añadir los certificados de test y de explotación
428 		List lCACertificates = getCAListExlotation();
429 		lCACertificates.addAll(getCAListTest());
430 		
431 		CAList caList;
432 		try {
433 			caList = new CAList (lCACertificates);
434 		} catch (NormalizeCertificateException e) {
435 			//-- Si algún certificado no puede ser normalizado lo pasamos como que no
436 			//-- se ha podido cargar
437 			logger.info ("[CertificadoSeudonimo.getCAList]::Alguno de los certificados de las CA no ha podido ser " +
438 					"normalizado a lo esperado por el proveedor criptográfico de Arangi", e);
439 			throw new CertificateCANotFoundException ("Alguno de los certificados de las CA no ha podido ser " +
440 					"normalizado a lo esperado por el proveedor criptográfico de Arangi", e);
441 		};
442 		
443 		//-- Añadir el fichero para validar los certificados de test
444 		try {
445 			caList.setValidationXML(ArangiUtil.loadFile("file/validation_data_accv_test.xml"));
446 		} catch (ValidationXMLException e) {
447 			//-- Si no se ha podido parsear el fichero de validación lo pasamos como que
448 			//-- no se han podido cargar los certificados de las CA
449 			logger.info ("[CertificadoSeudonimo.getCAList]::No ha sido posible parsear el fichero de validación XML", e);
450 			throw new CertificateCANotFoundException ("No ha sido posible parsear el fichero de validación XML", e);
451 		} catch (ResourceNotLoadedException e) {
452 			//-- Si no se encuentra pasaremos sin él, sólo que no funcionarán los certificados de test
453 			logger.info ("[CertificadoSeudonimo.getCAList]::No ha sido posible obtener el fichero de validación XML", e);
454 		}
455 		
456 		return caList;
457 	}
458 
459 	//-- Métodos protected
460 	
461 	/**
462 	 * Usado por la clase CertificateFactory para dar de alta la clase en la lista
463 	 * de tipos de certificados.
464 	 * 
465 	 * @return OID base de la política
466 	 */
467 	protected static String[] getBasePolicies () {
468 		return new String[] { 
469 				POLICY_IN_PKCS11_DEVICE, // certificados en tarjeta
470 				POLICY_IN_SOFTWARE_DEVICE, // certificados en software
471 				POLICY_IN_CLOUD // certificados en la nube 
472 		};
473 	}
474 
475 	//-- Métodos privados
476 	
477 	/*
478 	 * Obtiene la lista de certificados de CA y raíz que conforman las posibles cadenas
479 	 * de confianza de los certificados de explotación de esta clase. 
480 	 */
481 	private static List getCAListExlotation() throws CertificateCANotFoundException {
482 		
483 		//-- Nueva CA
484 		List lCACertificates = new ArrayList ();
485 		X509Certificate certificate = ArangiUtil.loadCertificate("certificate/ACCV-CA130-SHA256");
486 		setExplotationCACertificates.add(Certificate.getSubjectKeyIdentifier(certificate));
487 		lCACertificates.add(certificate);
488 		
489 		certificate = ArangiUtil.loadCertificate("certificate/ACCVRAIZ1");
490 		setExplotationCACertificates.add(Certificate.getSubjectKeyIdentifier(certificate));
491 		lCACertificates.add(certificate);
492 		
493 		return lCACertificates;
494 	}
495 	
496 	/*
497 	 * Obtiene la lista de certificados de CA y raíz que conforman las posibles cadenas
498 	 * de confianza de los certificados de test de esta clase. 
499 	 */
500 	private static List getCAListTest() throws CertificateCANotFoundException {
501 		
502 		List lCACertificates = new ArrayList ();
503 		X509Certificate certificate = ArangiUtil.loadCertificate("certificate/ACCVCATEST130");
504 		setTestCACertificates.add(Certificate.getSubjectKeyIdentifier(certificate));
505 		lCACertificates.add(certificate);
506 		
507 		certificate = ArangiUtil.loadCertificate("certificate/ROOTEJB4TEST");
508 		setTestCACertificates.add(Certificate.getSubjectKeyIdentifier(certificate));
509 		lCACertificates.add(certificate);
510 		
511 		return lCACertificates;
512 	}
513 
514 
515 }