1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package es.accv.arangi.base.certificate.validation;
22
23 import java.io.File;
24 import java.io.IOException;
25 import java.security.KeyStore;
26 import java.security.KeyStoreException;
27 import java.security.NoSuchAlgorithmException;
28 import java.security.cert.CertificateException;
29 import java.security.cert.X509Certificate;
30 import java.util.ArrayList;
31 import java.util.HashMap;
32 import java.util.Iterator;
33 import java.util.List;
34 import java.util.Map;
35
36 import org.apache.log4j.Logger;
37
38 import es.accv.arangi.base.ArangiObject;
39 import es.accv.arangi.base.algorithm.HashingAlgorithm;
40 import es.accv.arangi.base.certificate.Certificate;
41 import es.accv.arangi.base.device.KeyStoreManager;
42 import es.accv.arangi.base.exception.certificate.NormalizeCertificateException;
43 import es.accv.arangi.base.exception.certificate.ValidationXMLException;
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62 public class CAList extends ArangiObject {
63
64
65
66
67 private static final String VALIDATION_XML_FILE = "validation_data.xml";
68
69
70
71
72 private Logger logger = Logger.getLogger(CAList.class);
73
74
75
76
77 private HashMap<String, Map<String,X509Certificate>> hmCACertificates;
78
79
80
81
82 private HashMap<String, X509Certificate> hmAlternativeCACertificates;
83
84
85
86
87 private ValidationXML validationXML;
88
89
90
91
92 public CAList () {
93 logger.debug("[CAList()] :: Inicio");
94
95 hmCACertificates = new HashMap<String, Map<String,X509Certificate>> ();
96 hmAlternativeCACertificates = new HashMap<String, X509Certificate> ();
97 }
98
99
100
101
102
103
104
105 public CAList (List caList) throws NormalizeCertificateException {
106 logger.debug("[CAList(caList)] :: " + (caList==null?null:caList.size()));
107
108 hmCACertificates = new HashMap<String, Map<String,X509Certificate>> ();
109 hmAlternativeCACertificates = new HashMap<String, X509Certificate> ();
110
111
112 Iterator itCAs = caList.iterator();
113 while (itCAs.hasNext()) {
114 Object objectCertificate = itCAs.next();
115 Certificate certificate;
116 if (objectCertificate instanceof Certificate) {
117
118 certificate = (Certificate) objectCertificate;
119 } else {
120
121 try {
122 certificate = new Certificate((X509Certificate) objectCertificate);
123 } catch (ClassCastException e) {
124 logger.debug("[CAList(caList)] :: Some element in the list is not a valid X.509 certificate");
125 throw new NormalizeCertificateException ("Algún elemento de la lista no es un objeto X509Certificate");
126 } catch (NormalizeCertificateException e) {
127 logger.debug("[CAList(caList)] :: Cannot normalize as a bouncy castle X.509 certificate an element in the list");
128 throw e;
129 }
130 }
131 if (certificate.getSubjectKeyIdentifier() != null) {
132 try {
133 addToCACertificates(certificate.getSubjectKeyIdentifier(), certificate);
134 } catch (NoSuchAlgorithmException e) {
135 logger.info("[CAList(caList)] :: No se puede obtener el algoritmo de hashing del certificado:\n" + certificate);
136 }
137 }
138 hmAlternativeCACertificates.put(certificate.getCommonName(), certificate.toX509Certificate());
139 }
140 }
141
142
143
144
145
146
147
148
149
150
151
152 public CAList (File listSource) throws Exception {
153 logger.debug("[CAList(listSource)] :: " + listSource);
154
155
156 if (listSource == null) {
157 logger.info ("[CAList(listSource)] :: List source from CA certificates is a null value");
158 throw new Exception ("List source from CA certificates is a null value");
159 }
160
161 hmCACertificates = new HashMap<String, Map<String,X509Certificate>>();
162 hmAlternativeCACertificates = new HashMap<String, X509Certificate>();
163 if (listSource.isDirectory()) {
164
165
166 for (int i=0;i<listSource.listFiles().length;i++) {
167
168
169 if (listSource.listFiles()[i].isDirectory()) {
170 continue;
171 }
172
173
174 if (listSource.listFiles()[i].getName().equalsIgnoreCase(VALIDATION_XML_FILE)) {
175 validationXML = new ValidationXML (listSource.listFiles()[i], this);
176 } else {
177
178
179 try {
180 Certificate certificate = new Certificate(listSource.listFiles()[i]);
181 if (certificate.getSubjectKeyIdentifier() != null) {
182 addToCACertificates(certificate.getSubjectKeyIdentifier(), certificate);
183 }
184 hmAlternativeCACertificates.put(certificate.getCommonName(), certificate.toX509Certificate());
185 logger.debug ("[CAList(listSource)] :: File " + listSource.listFiles()[i].getAbsolutePath() + " imported as a CA certificate");
186 } catch (Exception e) {
187 logger.debug ("[CAList(listSource)] :: File " + listSource.listFiles()[i].getAbsolutePath() + " is not a X509Certificate", e);
188 }
189 }
190 }
191
192
193 if (hmCACertificates.isEmpty() && hmAlternativeCACertificates.isEmpty()) {
194 logger.info ("[CAList(listSource)] :: No X509 certificate is found in folder " + listSource.getAbsolutePath());
195 throw new Exception ("They are not X509 certificates in the folder " + listSource.getAbsolutePath());
196 }
197
198 } else {
199
200 try {
201 Certificate certificate = new Certificate(listSource);
202 if (certificate.getSubjectKeyIdentifier() != null) {
203 addToCACertificates(certificate.getSubjectKeyIdentifier(), certificate);
204 }
205 hmAlternativeCACertificates.put(certificate.getCommonName(), certificate.toX509Certificate());
206 } catch (Exception e) {
207 logger.info ("[CAList(listSource)] :: Error when getting the CA certificate from path " + listSource.getAbsolutePath(), e);
208 throw new Exception ("Error when getting the CA certificate from path ", e);
209 }
210 }
211
212 }
213
214
215
216
217
218
219 public ValidationXML getValidationXML () {
220 return validationXML;
221 }
222
223
224
225
226
227
228
229
230 public void setValidationXML (File validationXml) throws Exception {
231 this.validationXML = new ValidationXML (validationXml, this);
232 }
233
234
235
236
237
238
239
240
241 public void setValidationXML (byte[] validationXml) throws ValidationXMLException {
242 this.validationXML = new ValidationXML (validationXml, this);
243 }
244
245
246
247
248
249
250
251
252 public X509Certificate getCACertificate(X509Certificate x509Certificate) {
253
254 logger.debug("[CAList.getCACertificate]::Entrada");
255
256 Certificate certificate;
257 try {
258 certificate = new Certificate (x509Certificate);
259 logger.debug("[CAList.getCACertificate]::Certificado: " + certificate.getCommonName());
260 } catch (NormalizeCertificateException e) {
261 logger.info ("[CAList.getCACertificate]::El certificado no puede ser normalizado según el proveedor criptográfico de Arangí");
262 return null;
263 }
264
265
266 if (certificate.getIssuerKeyIdentifier() != null) {
267 Map<String,X509Certificate> map = (Map<String,X509Certificate>)hmCACertificates.get(certificate.getIssuerKeyIdentifier());
268 if (map == null || map.isEmpty()) {
269 return null;
270 }
271 if (map.containsKey(HashingAlgorithm.SHA512)) {
272 return map.get(HashingAlgorithm.SHA512);
273 }
274 if (map.containsKey(HashingAlgorithm.SHA384)) {
275 return map.get(HashingAlgorithm.SHA384);
276 }
277 if (map.containsKey(HashingAlgorithm.SHA256)) {
278 return map.get(HashingAlgorithm.SHA256);
279 }
280 if (map.containsKey(HashingAlgorithm.SHA1)) {
281 return map.get(HashingAlgorithm.SHA1);
282 }
283 return map.get(map.keySet().iterator().next());
284 }
285
286
287 logger.debug("[CAList.getCACertificate] :: El certificado no tiene SKI, probar por el CN del issuer");
288 if (certificate.getIssuerCommonName() != null) {
289 return (X509Certificate)hmAlternativeCACertificates.get(certificate.getIssuerCommonName());
290 }
291
292 logger.debug("[CAList.getCACertificate] :: Devolviendo null");
293 return null;
294
295 }
296
297
298
299
300
301
302
303
304
305
306 public X509Certificate getCACertificate(X509Certificate x509Certificate, String hashingAlgorithm) {
307
308 logger.debug("[CAList.getCACertificate]::Entrada");
309
310 Certificate certificate;
311 try {
312 certificate = new Certificate (x509Certificate);
313 logger.debug("[CAList.getCACertificate]::Certificado: " + certificate.getCommonName());
314 } catch (NormalizeCertificateException e) {
315 logger.info ("[CAList.getCACertificate]::El certificado no puede ser normalizado según el proveedor criptográfico de Arangí");
316 return null;
317 }
318
319
320 if (certificate.getIssuerKeyIdentifier() != null) {
321 Map<String,X509Certificate> map = (Map<String,X509Certificate>)hmCACertificates.get(certificate.getIssuerKeyIdentifier());
322 if (map == null) {
323 return null;
324 }
325 return map.get(hashingAlgorithm);
326 }
327
328
329 logger.debug("[CAList.getCACertificate] :: El certificado no tiene SKI, probar por el CN del issuer");
330 if (certificate.getIssuerCommonName() != null) {
331 X509Certificate x509Cert = (X509Certificate)hmAlternativeCACertificates.get(certificate.getIssuerCommonName());
332 if (x509Cert == null) {
333 return null;
334 }
335 try {
336 certificate = new Certificate (x509Cert);
337 if (certificate.getDigestAlgorithm().equalsIgnoreCase(hashingAlgorithm)) {
338 return x509Cert;
339 }
340 } catch (NormalizeCertificateException e) {
341 logger.info ("[CAList.getCACertificate]::El certificado no puede ser normalizado según el proveedor criptográfico de Arangí");
342 return null;
343 } catch (NoSuchAlgorithmException e) {
344 logger.info ("[CAList.getCACertificate]::No se puede obtener el algoritmo de hashing del certificado:\n" + certificate);
345 return null;
346 }
347 }
348
349 logger.debug("[CAList.getCACertificate] :: Devolviendo null");
350 return null;
351
352 }
353
354 public List<List<X509Certificate>> getCertificatesChain(X509Certificate x509Certificate) {
355
356 logger.debug("[CAList.getCertificatesChain]::Entrada");
357
358 List<List<X509Certificate>> resultado = new ArrayList<List<X509Certificate>>();
359 while (true) {
360 Certificate certificate;
361 try {
362 certificate = new Certificate (x509Certificate);
363 logger.debug("[CAList.getCertificatesChain]::Certificado: " + certificate.getCommonName());
364 if (certificate.isSelfSigned()) {
365 break;
366 }
367 } catch (NormalizeCertificateException e) {
368 logger.info ("[CAList.getCertificatesChain]::El certificado no puede ser normalizado según el proveedor criptográfico de Arangí");
369 return null;
370 }
371
372
373 if (certificate.getIssuerKeyIdentifier() != null) {
374 Map<String,X509Certificate> map = (Map<String,X509Certificate>)hmCACertificates.get(certificate.getIssuerKeyIdentifier());
375 if (map == null) {
376 break;
377 }
378 List<X509Certificate> lista = new ArrayList<X509Certificate>();
379 for (String key : map.keySet()) {
380 lista.add(map.get(key));
381 x509Certificate = map.get(key);
382 }
383 resultado.add(lista);
384 } else {
385
386 logger.debug("[CAList.getCertificatesChain] :: El certificado no tiene SKI, probar por el CN del issuer");
387 if (certificate.getIssuerCommonName() != null) {
388 X509Certificate x509Cert = (X509Certificate)hmAlternativeCACertificates.get(certificate.getIssuerCommonName());
389 if (x509Cert == null) {
390 break;
391 }
392 List<X509Certificate> lista = new ArrayList<X509Certificate>();
393 lista.add(x509Cert);
394 resultado.add(lista);
395
396 x509Certificate = x509Cert;
397 }
398 }
399
400 }
401
402 return resultado;
403
404 }
405
406
407
408
409
410
411 public boolean isEmpty() {
412 return hmCACertificates.isEmpty() && hmAlternativeCACertificates.isEmpty();
413 }
414
415
416
417
418
419
420
421
422 public boolean isOwned (X509Certificate x509Certificate) {
423 logger.debug("[CAList.isOwned]::Entrada");
424
425 Certificate certificate;
426 try {
427 certificate = new Certificate (x509Certificate);
428 logger.debug("[CAList.isOwned]::Certificado: " + certificate.getCommonName());
429 } catch (NormalizeCertificateException e) {
430 logger.info ("[CAList.isOwned]::El certificado no puede ser normalizado según el proveedor criptográfico de Arangí");
431 return false;
432 }
433
434
435 if (certificate.getIssuerKeyIdentifier() != null) {
436 return hmCACertificates.containsKey(certificate.getIssuerKeyIdentifier());
437 }
438
439
440 logger.debug("[CAList.isOwned] :: El certificado no tiene SKI, probar por el CN del issuer");
441 if (certificate.getIssuerCommonName() != null) {
442 return hmAlternativeCACertificates.containsKey(certificate.getIssuerCommonName());
443 }
444
445 logger.debug("[CAList.isOwned] :: Devolviendo null");
446 return false;
447
448 }
449
450
451
452
453
454
455
456
457 public boolean contains (X509Certificate certificate) {
458 Certificate cert;
459 try {
460 cert = new Certificate (certificate);
461 } catch (NormalizeCertificateException e) {
462 return false;
463 }
464 if (cert.getSubjectKeyIdentifier() != null) {
465 return hmCACertificates.containsKey(cert.getSubjectKeyIdentifier());
466 } else {
467 return hmAlternativeCACertificates.containsKey(cert.getCommonName());
468 }
469 }
470
471
472
473
474
475
476
477
478
479
480
481 public boolean containsKey (String base64SKI) {
482 return hmCACertificates.containsKey(base64SKI);
483 }
484
485
486
487
488
489
490 public List<X509Certificate> getCACertificates () {
491 List<X509Certificate> result = new ArrayList<X509Certificate> ();
492 for (Map<String,X509Certificate> map : hmCACertificates.values()) {
493 for (String key : map.keySet()) {
494 X509Certificate caCertificate = map.get(key);
495 result.add(caCertificate);
496 }
497 }
498 for (X509Certificate caCertificate : hmAlternativeCACertificates.values()) {
499 if (!result.contains(caCertificate)) {
500 result.add(caCertificate);
501 }
502 }
503
504 return result;
505 }
506
507
508
509
510
511
512 public void addCACertificate (X509Certificate caCertificate) {
513 Certificate cert = null;
514 try {
515 cert = new Certificate (caCertificate);
516 } catch (NormalizeCertificateException e) {
517 }
518 if (cert != null) {
519 if (cert.getSubjectKeyIdentifier() != null) {
520 try {
521 addToCACertificates(cert.getSubjectKeyIdentifier(), cert);
522 } catch (NoSuchAlgorithmException e) {
523 logger.info("[CAList(addCACertificate)] :: No se puede obtener el algoritmo de hashing del certificado:\n" + cert);
524 }
525 }
526 hmAlternativeCACertificates.put(cert.getCommonName(), caCertificate);
527 }
528 }
529
530
531
532
533
534
535
536
537
538 public KeyStore toKeyStore () throws KeyStoreException {
539
540
541 KeyStore ks = KeyStore.getInstance(KeyStoreManager.STORE_TYPE_JKS);
542 try {
543 ks.load(null, null);
544 } catch (NoSuchAlgorithmException e) {
545
546 } catch (CertificateException e) {
547
548 } catch (IOException e) {
549
550 }
551
552
553 List lCACertificates = getCACertificates();
554 int i = 0;
555 for (Iterator iterator = lCACertificates.iterator(); iterator.hasNext();) {
556 X509Certificate caCertificate = (X509Certificate) iterator.next();
557 ks.setCertificateEntry("alias" + i, caCertificate);
558 i++;
559 }
560
561 return ks;
562 }
563
564
565
566 private void addToCACertificates(String subjectKeyIdentifier,
567 Certificate certificate) throws NoSuchAlgorithmException {
568 Map<String,X509Certificate> mapCaCertificates = hmCACertificates.get(subjectKeyIdentifier);
569 if (mapCaCertificates == null) {
570 mapCaCertificates = new HashMap<String, X509Certificate>();
571 }
572 mapCaCertificates.put(certificate.getDigestAlgorithm(), certificate.toX509Certificate());
573 hmCACertificates.put(subjectKeyIdentifier, mapCaCertificates);
574 }
575
576
577 }