1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  package org.waarp.common.crypto.ssl;
21  
22  import org.joda.time.DateTime;
23  import org.waarp.common.exception.CryptoException;
24  import org.waarp.common.file.FileUtils;
25  import org.waarp.common.logging.WaarpLogger;
26  import org.waarp.common.logging.WaarpLoggerFactory;
27  
28  import javax.net.ssl.KeyManagerFactory;
29  import javax.net.ssl.TrustManagerFactory;
30  import java.io.File;
31  import java.io.FileInputStream;
32  import java.io.FileNotFoundException;
33  import java.io.FileOutputStream;
34  import java.io.IOException;
35  import java.security.Key;
36  import java.security.KeyStore;
37  import java.security.KeyStoreException;
38  import java.security.NoSuchAlgorithmException;
39  import java.security.UnrecoverableKeyException;
40  import java.security.cert.Certificate;
41  import java.security.cert.CertificateException;
42  import java.security.cert.CertificateFactory;
43  import java.security.cert.X509Certificate;
44  import java.util.Date;
45  import java.util.Enumeration;
46  
47  import static org.waarp.common.digest.WaarpBC.*;
48  
49  
50  
51  
52  public class WaarpSecureKeyStore {
53    private static final String CANNOT_SAVE_TO_FILE_KEY_STORE_INSTANCE =
54        "Cannot save to file KeyStore Instance";
55  
56    private static final String CANNOT_CREATE_KEY_MANAGER_FACTORY_INSTANCE =
57        "Cannot create KeyManagerFactory Instance";
58  
59    private static final String CANNOT_CREATE_KEY_STORE_INSTANCE =
60        "Cannot create KeyStore Instance";
61  
62    
63  
64  
65    private static final WaarpLogger logger =
66        WaarpLoggerFactory.getLogger(WaarpSecureKeyStore.class);
67    private static final String CANNOT_CREATE_TRUST_MANAGER_FACTORY_INSTANCE =
68        "Cannot create TrustManagerFactory Instance";
69    private static final String CANNOT_CREATE_KEY_TRUST_STORE_INSTANCE =
70        "Cannot create keyTrustStore Instance";
71    private static final String CANNOT_SAVE_TO_FILE_KEY_TRUST_STORE_INSTANCE =
72        "Cannot save to file keyTrustStore Instance";
73  
74    static {
75      initializedTlsContext();
76    }
77  
78    private String keyStoreFilename;
79    private KeyStore keyStore;
80    private KeyManagerFactory keyManagerFactory;
81    private String keyStorePasswd;
82    private String keyPassword;
83    private WaarpSecureTrustManagerFactory secureTrustManagerFactory;
84    private KeyStore keyTrustStore;
85    private String trustStorePasswd;
86  
87    
88  
89  
90  
91  
92  
93  
94  
95    public WaarpSecureKeyStore(final String keyStorePasswd,
96                               final String keyPassword) throws CryptoException {
97      this.keyStorePasswd = keyStorePasswd;
98      this.keyPassword = keyPassword;
99      try {
100       keyStore = KeyStore.getInstance("JKS");
101     } catch (final KeyStoreException e) {
102       logger.error(CANNOT_CREATE_KEY_STORE_INSTANCE, e);
103       throw new CryptoException(CANNOT_CREATE_KEY_STORE_INSTANCE, e);
104     }
105     try {
106       
107       keyStore.load(null, getKeyStorePassword());
108     } catch (final NoSuchAlgorithmException e) {
109       logger.error(CANNOT_CREATE_KEY_STORE_INSTANCE, e);
110       throw new CryptoException(CANNOT_CREATE_KEY_STORE_INSTANCE, e);
111     } catch (final CertificateException e) {
112       logger.error(CANNOT_CREATE_KEY_STORE_INSTANCE, e);
113       throw new CryptoException(CANNOT_CREATE_KEY_STORE_INSTANCE, e);
114     } catch (final FileNotFoundException e) {
115       logger.error(CANNOT_CREATE_KEY_STORE_INSTANCE, e);
116       throw new CryptoException(CANNOT_CREATE_KEY_STORE_INSTANCE, e);
117     } catch (final IOException e) {
118       logger.error(CANNOT_CREATE_KEY_STORE_INSTANCE, e);
119       throw new CryptoException(CANNOT_CREATE_KEY_STORE_INSTANCE, e);
120     }
121     initKeyManagerFactory();
122   }
123 
124   
125 
126 
127 
128 
129 
130 
131 
132 
133   public WaarpSecureKeyStore(final String keyStoreFilename,
134                              final String keyStorePasswd,
135                              final String keyPassword) throws CryptoException {
136     initKeyStore(keyStoreFilename, keyStorePasswd, keyPassword);
137   }
138 
139   
140 
141 
142 
143 
144 
145 
146 
147 
148 
149 
150 
151 
152 
153 
154   public WaarpSecureKeyStore(final String keyStoreFilename,
155                              final String keyStorePasswd,
156                              final String keyPassword,
157                              final String trustStoreFilename,
158                              final String trustStorePasswd,
159                              final boolean needClientAuthent)
160       throws CryptoException {
161     
162     initKeyStore(keyStoreFilename, keyStorePasswd, keyPassword);
163     
164     if (trustStoreFilename != null) {
165       initTrustStore(trustStoreFilename, trustStorePasswd, needClientAuthent);
166     } else {
167       initEmptyTrustStore();
168     }
169   }
170 
171   
172 
173 
174 
175 
176 
177 
178 
179 
180   public final void initKeyStore(final String keystoreFilename,
181                                  final String keystorePasswd,
182                                  final String keyPasswordNew)
183       throws CryptoException {
184     keyStoreFilename = keystoreFilename;
185     keyStorePasswd = keystorePasswd;
186     keyPassword = keyPasswordNew;
187     
188     try {
189       keyStore = KeyStore.getInstance("JKS");
190     } catch (final KeyStoreException e) {
191       logger.error(CANNOT_CREATE_KEY_STORE_INSTANCE, e);
192       throw new CryptoException(CANNOT_CREATE_KEY_STORE_INSTANCE, e);
193     }
194     FileInputStream inputStream = null;
195     try {
196       final File temp = new File(keystoreFilename).getAbsoluteFile();
197       inputStream = new FileInputStream(temp);
198       keyStore.load(inputStream, getKeyStorePassword());
199     } catch (final NoSuchAlgorithmException e) {
200       logger.error(CANNOT_CREATE_KEY_STORE_INSTANCE, e);
201       throw new CryptoException(CANNOT_CREATE_KEY_STORE_INSTANCE, e);
202     } catch (final CertificateException e) {
203       logger.error(CANNOT_CREATE_KEY_STORE_INSTANCE, e);
204       throw new CryptoException(CANNOT_CREATE_KEY_STORE_INSTANCE, e);
205     } catch (final FileNotFoundException e) {
206       logger.error(CANNOT_CREATE_KEY_STORE_INSTANCE, e);
207       throw new CryptoException(CANNOT_CREATE_KEY_STORE_INSTANCE, e);
208     } catch (final IOException e) {
209       logger.error(CANNOT_CREATE_KEY_STORE_INSTANCE, e);
210       throw new CryptoException(CANNOT_CREATE_KEY_STORE_INSTANCE, e);
211     } finally {
212       FileUtils.close(inputStream);
213     }
214     checkExpiryDate(keyStore);
215     initKeyManagerFactory();
216   }
217 
218   
219 
220 
221 
222 
223   final void initKeyManagerFactory() throws CryptoException {
224     try {
225       keyManagerFactory = KeyManagerFactory.getInstance(
226           KeyManagerFactory.getDefaultAlgorithm());
227     } catch (final NoSuchAlgorithmException e) {
228       logger.error(CANNOT_CREATE_KEY_MANAGER_FACTORY_INSTANCE, e);
229       throw new CryptoException(CANNOT_CREATE_KEY_MANAGER_FACTORY_INSTANCE, e);
230     }
231     try {
232       keyManagerFactory.init(keyStore, getCertificatePassword());
233     } catch (final UnrecoverableKeyException e) {
234       logger.error(CANNOT_CREATE_KEY_MANAGER_FACTORY_INSTANCE, e);
235       throw new CryptoException(CANNOT_CREATE_KEY_MANAGER_FACTORY_INSTANCE, e);
236     } catch (final KeyStoreException e) {
237       logger.error(CANNOT_CREATE_KEY_MANAGER_FACTORY_INSTANCE, e);
238       throw new CryptoException(CANNOT_CREATE_KEY_MANAGER_FACTORY_INSTANCE, e);
239     } catch (final NoSuchAlgorithmException e) {
240       logger.error(CANNOT_CREATE_KEY_MANAGER_FACTORY_INSTANCE, e);
241       throw new CryptoException(CANNOT_CREATE_KEY_MANAGER_FACTORY_INSTANCE, e);
242     }
243   }
244 
245   
246 
247 
248 
249 
250 
251 
252   public final boolean deleteKeyFromKeyStore(final String alias) {
253     try {
254       keyStore.deleteEntry(alias);
255     } catch (final KeyStoreException e) {
256       logger.error("Cannot delete Key from KeyStore Instance", e);
257       return false;
258     }
259     return true;
260   }
261 
262   
263 
264 
265 
266 
267 
268 
269 
270 
271   public final boolean setKeytoKeyStore(final String alias, final Key key,
272                                         final Certificate[] chain) {
273     try {
274       keyStore.setKeyEntry(alias, key, getCertificatePassword(), chain);
275     } catch (final KeyStoreException e) {
276       logger.error("Cannot add Key and Certificates to KeyStore Instance", e);
277       return false;
278     }
279     return true;
280   }
281 
282   
283 
284 
285 
286 
287 
288 
289   public final boolean saveKeyStore(final String filename) {
290     FileOutputStream fos = null;
291     try {
292       fos = new FileOutputStream(filename);
293       try {
294         keyStore.store(fos, getKeyStorePassword());
295       } catch (final KeyStoreException e) {
296         logger.error(CANNOT_SAVE_TO_FILE_KEY_STORE_INSTANCE, e);
297         return false;
298       } catch (final NoSuchAlgorithmException e) {
299         logger.error(CANNOT_SAVE_TO_FILE_KEY_STORE_INSTANCE, e);
300         return false;
301       } catch (final CertificateException e) {
302         logger.error(CANNOT_SAVE_TO_FILE_KEY_STORE_INSTANCE, e);
303         return false;
304       } catch (final IOException e) {
305         logger.error(CANNOT_SAVE_TO_FILE_KEY_STORE_INSTANCE, e);
306         return false;
307       }
308     } catch (final FileNotFoundException e) {
309       logger.error(CANNOT_SAVE_TO_FILE_KEY_STORE_INSTANCE, e);
310       return false;
311     } finally {
312       FileUtils.close(fos);
313     }
314     return true;
315   }
316 
317   
318 
319 
320 
321 
322 
323 
324 
325 
326 
327 
328   public final void initTrustStore(final String truststoreFilename,
329                                    final String truststorePasswd,
330                                    final boolean needClientAuthent)
331       throws CryptoException {
332     trustStorePasswd = truststorePasswd;
333     try {
334       keyTrustStore = KeyStore.getInstance("JKS");
335     } catch (final KeyStoreException e) {
336       logger.error(CANNOT_CREATE_TRUST_MANAGER_FACTORY_INSTANCE, e);
337       throw new CryptoException(CANNOT_CREATE_TRUST_MANAGER_FACTORY_INSTANCE,
338                                 e);
339     }
340     FileInputStream inputStream = null;
341     try {
342       final File temp = new File(truststoreFilename).getAbsoluteFile();
343       inputStream = new FileInputStream(temp);
344       keyTrustStore.load(inputStream, getKeyTrustStorePassword());
345     } catch (final NoSuchAlgorithmException e) {
346       logger.error(CANNOT_CREATE_TRUST_MANAGER_FACTORY_INSTANCE, e);
347       throw new CryptoException(CANNOT_CREATE_TRUST_MANAGER_FACTORY_INSTANCE,
348                                 e);
349     } catch (final CertificateException e) {
350       logger.error(CANNOT_CREATE_TRUST_MANAGER_FACTORY_INSTANCE, e);
351       throw new CryptoException(CANNOT_CREATE_TRUST_MANAGER_FACTORY_INSTANCE,
352                                 e);
353     } catch (final FileNotFoundException e) {
354       logger.error(CANNOT_CREATE_TRUST_MANAGER_FACTORY_INSTANCE, e);
355       throw new CryptoException(CANNOT_CREATE_TRUST_MANAGER_FACTORY_INSTANCE,
356                                 e);
357     } catch (final IOException e) {
358       logger.error(CANNOT_CREATE_TRUST_MANAGER_FACTORY_INSTANCE, e);
359       throw new CryptoException(CANNOT_CREATE_TRUST_MANAGER_FACTORY_INSTANCE,
360                                 e);
361     } finally {
362       FileUtils.close(inputStream);
363     }
364     checkExpiryDate(keyTrustStore);
365     final TrustManagerFactory trustManagerFactory;
366     try {
367       trustManagerFactory = TrustManagerFactory.getInstance(
368           KeyManagerFactory.getDefaultAlgorithm());
369     } catch (final NoSuchAlgorithmException e1) {
370       logger.error(CANNOT_CREATE_TRUST_MANAGER_FACTORY_INSTANCE, e1);
371       throw new CryptoException(CANNOT_CREATE_TRUST_MANAGER_FACTORY_INSTANCE,
372                                 e1);
373     }
374     try {
375       trustManagerFactory.init(keyTrustStore);
376     } catch (final KeyStoreException e1) {
377       logger.error(CANNOT_CREATE_TRUST_MANAGER_FACTORY_INSTANCE, e1);
378       throw new CryptoException(CANNOT_CREATE_TRUST_MANAGER_FACTORY_INSTANCE,
379                                 e1);
380     }
381     try {
382       secureTrustManagerFactory =
383           new WaarpSecureTrustManagerFactory(trustManagerFactory,
384                                              needClientAuthent);
385     } catch (final CryptoException e) {
386       logger.error(CANNOT_CREATE_TRUST_MANAGER_FACTORY_INSTANCE, e);
387       throw new CryptoException(CANNOT_CREATE_TRUST_MANAGER_FACTORY_INSTANCE,
388                                 e);
389     }
390   }
391 
392   
393 
394 
395 
396 
397   public final boolean initEmptyTrustStore() {
398     trustStorePasswd = "secret";
399     try {
400       keyTrustStore = KeyStore.getInstance("JKS");
401     } catch (final KeyStoreException e) {
402       logger.error(CANNOT_CREATE_KEY_TRUST_STORE_INSTANCE, e);
403       return false;
404     }
405     try {
406       
407       keyTrustStore.load(null, getKeyTrustStorePassword());
408     } catch (final NoSuchAlgorithmException e) {
409       logger.error(CANNOT_CREATE_KEY_TRUST_STORE_INSTANCE, e);
410       return false;
411     } catch (final CertificateException e) {
412       logger.error(CANNOT_CREATE_KEY_TRUST_STORE_INSTANCE, e);
413       return false;
414     } catch (final FileNotFoundException e) {
415       logger.error(CANNOT_CREATE_KEY_TRUST_STORE_INSTANCE, e);
416       return false;
417     } catch (final IOException e) {
418       logger.error(CANNOT_CREATE_KEY_TRUST_STORE_INSTANCE, e);
419       return false;
420     }
421     secureTrustManagerFactory = new WaarpSecureTrustManagerFactory();
422     return true;
423   }
424 
425   
426 
427 
428 
429 
430 
431 
432   public final boolean deleteKeyFromTrustStore(final String alias) {
433     try {
434       keyStore.deleteEntry(alias);
435     } catch (final KeyStoreException e) {
436       logger.error("Cannot delete Key from keyTrustStore Instance", e);
437       return false;
438     }
439     return true;
440   }
441 
442   
443 
444 
445 
446 
447 
448 
449 
450   public final boolean setKeytoTrustStore(final String alias,
451                                           final Certificate cert) {
452     try {
453       keyStore.setCertificateEntry(alias, cert);
454     } catch (final KeyStoreException e) {
455       logger.error("Cannot add Certificate to keyTrustStore Instance", e);
456       return false;
457     }
458     return true;
459   }
460 
461   
462 
463 
464 
465 
466 
467 
468   public final boolean saveTrustStore(final String filename) {
469     FileOutputStream fos = null;
470     try {
471       fos = new FileOutputStream(filename);
472       try {
473         keyTrustStore.store(fos, getKeyTrustStorePassword());
474       } catch (final KeyStoreException e) {
475         logger.error(CANNOT_SAVE_TO_FILE_KEY_TRUST_STORE_INSTANCE, e);
476         return false;
477       } catch (final NoSuchAlgorithmException e) {
478         logger.error(CANNOT_SAVE_TO_FILE_KEY_TRUST_STORE_INSTANCE, e);
479         return false;
480       } catch (final CertificateException e) {
481         logger.error(CANNOT_SAVE_TO_FILE_KEY_TRUST_STORE_INSTANCE, e);
482         return false;
483       } catch (final IOException e) {
484         logger.error(CANNOT_SAVE_TO_FILE_KEY_TRUST_STORE_INSTANCE, e);
485         return false;
486       }
487     } catch (final FileNotFoundException e) {
488       logger.error(CANNOT_SAVE_TO_FILE_KEY_TRUST_STORE_INSTANCE, e);
489       return false;
490     } finally {
491       FileUtils.close(fos);
492     }
493     return true;
494   }
495 
496   
497 
498 
499 
500 
501 
502 
503 
504 
505 
506   public static Certificate loadX509Certificate(final String filename)
507       throws CertificateException, FileNotFoundException {
508     final CertificateFactory cf = CertificateFactory.getInstance("X.509");
509     final FileInputStream in = new FileInputStream(filename);
510     try {
511       return cf.generateCertificate(in);
512     } finally {
513       FileUtils.close(in);
514     }
515   }
516 
517   
518 
519 
520   public final char[] getCertificatePassword() {
521     if (keyPassword != null) {
522       return keyPassword.toCharArray();
523     }
524     return "nopwd".toCharArray();
525   }
526 
527   
528 
529 
530   public final char[] getKeyStorePassword() {
531     if (keyStorePasswd != null) {
532       return keyStorePasswd.toCharArray();
533     }
534     return "nopwd".toCharArray();
535   }
536 
537   
538 
539 
540   public final char[] getKeyTrustStorePassword() {
541     if (trustStorePasswd != null) {
542       return trustStorePasswd.toCharArray();
543     }
544     return "nopwd".toCharArray();
545   }
546 
547   
548 
549 
550   public final String getKeyStoreFilename() {
551     return keyStoreFilename;
552   }
553 
554   
555 
556 
557   public final WaarpSecureTrustManagerFactory getSecureTrustManagerFactory() {
558     return secureTrustManagerFactory;
559   }
560 
561   
562 
563 
564   public final KeyManagerFactory getKeyManagerFactory() {
565     return keyManagerFactory;
566   }
567 
568   
569 
570 
571   public final KeyStore getKeyStore() {
572     return keyStore;
573   }
574 
575   
576 
577 
578   public final KeyStore getKeyTrustStore() {
579     return keyTrustStore;
580   }
581 
582   
583 
584 
585 
586 
587   public static boolean checkExpiryDate(final KeyStore keystore) {
588     final Enumeration<String> aliases;
589     try {
590       aliases = keystore.aliases();
591     } catch (final KeyStoreException e) {
592       logger.warn("Cannot get Aliases: {}", e.getMessage());
593       return true;
594     }
595     Date expiryDate;
596     boolean valid = true;
597     for (; aliases.hasMoreElements(); ) {
598       final String alias = aliases.nextElement();
599       try {
600         expiryDate =
601             ((X509Certificate) keystore.getCertificate(alias)).getNotAfter();
602         final DateTime dateTime = new DateTime(expiryDate);
603         if (dateTime.isBeforeNow()) {
604           logger.error("Certificate {} has an expiry date before today: {}",
605                        alias, dateTime);
606           valid = false;
607         } else {
608           logger.debug("Certificate {} has an expiry date over today: {}",
609                        alias, dateTime);
610         }
611       } catch (final KeyStoreException e) {
612         logger.warn("Cannot get Expiry Date: {}", e.getMessage());
613       }
614     }
615     return valid;
616   }
617 }