View Javadoc

1   /**
2      This file is part of GoldenGate Project (named also GoldenGate or GG).
3   
4      Copyright 2009, Frederic Bregier, and individual contributors by the @author
5      tags. See the COPYRIGHT.txt in the distribution for a full listing of
6      individual contributors.
7   
8      All GoldenGate Project is free software: you can redistribute it and/or 
9      modify it under the terms of the GNU General Public License as published 
10     by the Free Software Foundation, either version 3 of the License, or
11     (at your option) any later version.
12  
13     GoldenGate is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16     GNU General Public License for more details.
17  
18     You should have received a copy of the GNU General Public License
19     along with GoldenGate .  If not, see <http://www.gnu.org/licenses/>.
20   */
21  package goldengate.common.crypto.ssl;
22  
23  import java.io.FileInputStream;
24  import java.io.FileNotFoundException;
25  import java.io.FileOutputStream;
26  import java.io.IOException;
27  import java.security.Key;
28  import java.security.KeyStore;
29  import java.security.KeyStoreException;
30  import java.security.NoSuchAlgorithmException;
31  import java.security.UnrecoverableKeyException;
32  import java.security.cert.Certificate;
33  import java.security.cert.CertificateException;
34  import java.security.cert.CertificateFactory;
35  
36  import javax.net.ssl.KeyManagerFactory;
37  import javax.net.ssl.TrustManagerFactory;
38  
39  import goldengate.common.exception.CryptoException;
40  import goldengate.common.logging.GgInternalLogger;
41  import goldengate.common.logging.GgInternalLoggerFactory;
42  
43  /**
44   * SecureKeyStore for SLL
45   *
46   * @author Frederic Bregier
47   *
48   */
49  public class GgSecureKeyStore {
50      /**
51       * Internal Logger
52       */
53      private static final GgInternalLogger logger = GgInternalLoggerFactory
54              .getLogger(GgSecureKeyStore.class);
55  
56      private KeyStore keyStore;
57      private KeyManagerFactory keyManagerFactory;
58      private String keyStorePasswd;
59      private String keyPassword;
60      private GgSecureTrustManagerFactory secureTrustManagerFactory;
61      private KeyStore keyTrustStore;
62      private String trustStorePasswd;
63  
64      /**
65       * Initialize empty KeyStore. No TrustStore is internally created.
66       * @param _keyStorePasswd
67       * @param _keyPassword
68       * @throws CryptoException
69       */
70      public GgSecureKeyStore(String _keyStorePasswd, String _keyPassword) throws CryptoException {
71          keyStorePasswd = _keyStorePasswd;
72          keyPassword = _keyPassword;
73          try {
74              keyStore = KeyStore.getInstance("JKS");
75          } catch (KeyStoreException e) {
76              logger.error("Cannot create KeyStore Instance", e);
77              throw new CryptoException("Cannot create KeyStore Instance", e);
78          }
79          try {
80              // Empty keyStore created so null for the InputStream
81              keyStore.load(null,
82                      getKeyStorePassword());
83          } catch (NoSuchAlgorithmException e) {
84              logger.error("Cannot create KeyStore Instance", e);
85              throw new CryptoException("Cannot create KeyStore Instance", e);
86          } catch (CertificateException e) {
87              logger.error("Cannot create KeyStore Instance", e);
88              throw new CryptoException("Cannot create KeyStore Instance", e);
89          } catch (FileNotFoundException e) {
90              logger.error("Cannot create KeyStore Instance", e);
91              throw new CryptoException("Cannot create KeyStore Instance", e);
92          } catch (IOException e) {
93              logger.error("Cannot create KeyStore Instance", e);
94              throw new CryptoException("Cannot create KeyStore Instance", e);
95          }
96          initKeyManagerFactory();
97      }
98      /**
99       * Initialize the SecureKeyStore with no TrustStore from file
100      * @param keyStoreFilename
101      * @param _keyStorePasswd
102      * @param _keyPassword
103      * @throws CryptoException
104      */
105     public GgSecureKeyStore(
106             String keyStoreFilename, String _keyStorePasswd, String _keyPassword) throws CryptoException {
107         initKeyStore(keyStoreFilename, _keyStorePasswd, _keyPassword);
108     }
109     /**
110      * Initialize the SecureKeyStore and TrustStore from files
111      * @param keyStoreFilename
112      * @param _keyStorePasswd
113      * @param _keyPassword
114      * @param trustStoreFilename if Null, no TrustKeyStore will be created
115      * @param _trustStorePasswd
116      * @param needClientAuthent True if the TrustStore is also used for Client Authentication
117      * @throws CryptoException
118      */
119     public GgSecureKeyStore(
120             String keyStoreFilename, String _keyStorePasswd, String _keyPassword,
121             String trustStoreFilename, String _trustStorePasswd, boolean needClientAuthent) throws CryptoException {
122         // Create the KeyStore
123         initKeyStore(keyStoreFilename, _keyStorePasswd, _keyPassword);
124         // Now create the TrustKeyStore
125         if (trustStoreFilename != null) {
126             initTrustStore(trustStoreFilename, _trustStorePasswd, needClientAuthent);
127         } else {
128             initEmptyTrustStore();
129         }
130     }
131     /**
132      * Initialize the SecureKeyStore with no TrustStore from file
133      * @param keyStoreFilename
134      * @param _keyStorePasswd
135      * @param _keyPassword
136      * @throws CryptoException
137      */
138     public void initKeyStore(String keyStoreFilename, String _keyStorePasswd, String _keyPassword)
139     throws CryptoException {
140         keyStorePasswd = _keyStorePasswd;
141         keyPassword = _keyPassword;
142         // First keyStore itself
143         try {
144             keyStore = KeyStore.getInstance("JKS");
145         } catch (KeyStoreException e) {
146             logger.error("Cannot create KeyStore Instance", e);
147             throw new CryptoException("Cannot create KeyStore Instance", e);
148         }
149         FileInputStream inputStream;
150         try {
151             inputStream = new FileInputStream(keyStoreFilename);
152             keyStore.load(inputStream, getKeyStorePassword());
153         } catch (NoSuchAlgorithmException e) {
154             logger.error("Cannot create KeyStore Instance", e);
155             throw new CryptoException("Cannot create KeyStore Instance", e);
156         } catch (CertificateException e) {
157             logger.error("Cannot create KeyStore Instance", e);
158             throw new CryptoException("Cannot create KeyStore Instance", e);
159         } catch (FileNotFoundException e) {
160             logger.error("Cannot create KeyStore Instance", e);
161             throw new CryptoException("Cannot create KeyStore Instance", e);
162         } catch (IOException e) {
163             logger.error("Cannot create KeyStore Instance", e);
164             throw new CryptoException("Cannot create KeyStore Instance", e);
165         }
166         try {
167             inputStream.close();
168         } catch (IOException e) {
169         }
170         initKeyManagerFactory();
171     }
172     /**
173      * Init KeyManagerFactory
174      * @throws CryptoException
175      */
176     void initKeyManagerFactory() throws CryptoException {
177         try {
178             keyManagerFactory = KeyManagerFactory.getInstance(
179                     KeyManagerFactory.getDefaultAlgorithm());
180             //"SunX509");
181         } catch (NoSuchAlgorithmException e) {
182             logger.error("Cannot create KeyManagerFactory Instance", e);
183             throw new CryptoException("Cannot create KeyManagerFactory Instance", e);
184         }
185         try {
186             keyManagerFactory.init(keyStore, getCertificatePassword());
187         } catch (UnrecoverableKeyException e) {
188             logger.error("Cannot create KeyManagerFactory Instance", e);
189             throw new CryptoException("Cannot create KeyManagerFactory Instance", e);
190         } catch (KeyStoreException e) {
191             logger.error("Cannot create KeyManagerFactory Instance", e);
192             throw new CryptoException("Cannot create KeyManagerFactory Instance", e);
193         } catch (NoSuchAlgorithmException e) {
194             logger.error("Cannot create KeyManagerFactory Instance", e);
195             throw new CryptoException("Cannot create KeyManagerFactory Instance", e);
196         }
197     }
198     /**
199      * Delete a Key from the KeyStore based on its alias
200      * @param alias
201      * @return True if entry is deleted
202      */
203     public boolean deleteKeyFromKeyStore(String alias) {
204         try {
205             keyStore.deleteEntry(alias);
206         } catch (KeyStoreException e) {
207             logger.error("Cannot delete Key from KeyStore Instance", e);
208             return false;
209         }
210         return true;
211     }
212     /**
213      * Add a Key and its certificates into the KeyStore based on its alias
214      * @param alias
215      * @param key
216      * @param chain
217      * @return True if entry is added
218      */
219     public boolean setKeytoKeyStore(String alias, Key key, Certificate[] chain) {
220         try {
221             keyStore.setKeyEntry(alias, key, getCertificatePassword(), chain);
222         } catch (KeyStoreException e) {
223             logger.error("Cannot add Key and Certificates to KeyStore Instance", e);
224             return false;
225         }
226         return true;
227     }
228     /**
229      * Save a KeyStore to a file
230      * @param filename
231      * @return True if keyStore is saved to file
232      */
233     public boolean saveKeyStore(String filename) {
234         FileOutputStream fos;
235         try {
236             fos = new FileOutputStream(filename);
237         } catch (FileNotFoundException e) {
238             logger.error("Cannot save to file KeyStore Instance", e);
239             return false;
240         }
241         try {
242             keyStore.store(fos, getKeyStorePassword());
243         } catch (KeyStoreException e) {
244             logger.error("Cannot save to file KeyStore Instance", e);
245             return false;
246         } catch (NoSuchAlgorithmException e) {
247             logger.error("Cannot save to file KeyStore Instance", e);
248             return false;
249         } catch (CertificateException e) {
250             logger.error("Cannot save to file KeyStore Instance", e);
251             return false;
252         } catch (IOException e) {
253             logger.error("Cannot save to file KeyStore Instance", e);
254             return false;
255         }
256         try {
257             fos.close();
258         } catch (IOException e) {
259         }
260         return true;
261     }
262     /**
263      * Initialize the TrustStore from a filename and its password
264      * @param trustStoreFilename
265      * @param _trustStorePasswd
266      * @param needClientAuthent True if the TrustStore is also to authenticate clients
267      * @throws CryptoException
268      */
269     public void initTrustStore(String trustStoreFilename, String _trustStorePasswd, boolean needClientAuthent) throws CryptoException {
270         trustStorePasswd = _trustStorePasswd;
271         try {
272             keyTrustStore = KeyStore.getInstance("JKS");
273         } catch (KeyStoreException e) {
274             logger.error("Cannot create TrustManagerFactory Instance", e);
275             throw new CryptoException("Cannot create TrustManagerFactory Instance", e);
276         }
277         FileInputStream inputStream;
278         try {
279             inputStream = new FileInputStream(trustStoreFilename);
280             keyTrustStore.load(inputStream, getKeyTrustStorePassword());
281         } catch (NoSuchAlgorithmException e) {
282             logger.error("Cannot create TrustManagerFactory Instance", e);
283             throw new CryptoException("Cannot create TrustManagerFactory Instance", e);
284         } catch (CertificateException e) {
285             logger.error("Cannot create TrustManagerFactory Instance", e);
286             throw new CryptoException("Cannot create TrustManagerFactory Instance", e);
287         } catch (FileNotFoundException e) {
288             logger.error("Cannot create TrustManagerFactory Instance", e);
289             throw new CryptoException("Cannot create TrustManagerFactory Instance", e);
290         } catch (IOException e) {
291             logger.error("Cannot create TrustManagerFactory Instance", e);
292             throw new CryptoException("Cannot create TrustManagerFactory Instance", e);
293         }
294         try {
295             inputStream.close();
296         } catch (IOException e2) {
297         }
298         TrustManagerFactory trustManagerFactory = null;
299         try {
300             trustManagerFactory = TrustManagerFactory.getInstance(
301                     KeyManagerFactory.getDefaultAlgorithm());
302         } catch (NoSuchAlgorithmException e1) {
303             logger.error("Cannot create TrustManagerFactory Instance", e1);
304             throw new CryptoException("Cannot create TrustManagerFactory Instance", e1);
305         }
306         try {
307             trustManagerFactory.init(keyTrustStore);
308         } catch (KeyStoreException e1) {
309             logger.error("Cannot create TrustManagerFactory Instance", e1);
310             throw new CryptoException("Cannot create TrustManagerFactory Instance", e1);
311         }
312         try {
313             secureTrustManagerFactory = new GgSecureTrustManagerFactory(trustManagerFactory, needClientAuthent);
314         } catch (CryptoException e) {
315             logger.error("Cannot create TrustManagerFactory Instance", e);
316             throw new CryptoException("Cannot create TrustManagerFactory Instance", e);
317         }
318     }
319     /**
320      * Initialize an empty TrustStore
321      * @return True if correctly initialized empty
322      */
323     public boolean initEmptyTrustStore() {
324         trustStorePasswd = "secret";
325         try {
326             keyTrustStore = KeyStore.getInstance("JKS");
327         } catch (KeyStoreException e) {
328             logger.error("Cannot create keyTrustStore Instance", e);
329             return false;
330         }
331         try {
332             // Empty keyTrustStore created so null for the InputStream
333             keyTrustStore.load(null,
334                     getKeyTrustStorePassword());
335         } catch (NoSuchAlgorithmException e) {
336             logger.error("Cannot create keyTrustStore Instance", e);
337             return false;
338         } catch (CertificateException e) {
339             logger.error("Cannot create keyTrustStore Instance", e);
340             return false;
341         } catch (FileNotFoundException e) {
342             logger.error("Cannot create keyTrustStore Instance", e);
343             return false;
344         } catch (IOException e) {
345             logger.error("Cannot create keyTrustStore Instance", e);
346             return false;
347         }
348         secureTrustManagerFactory = new GgSecureTrustManagerFactory();
349         return true;
350     }
351     /**
352      * Delete a Key from the TrustStore based on its alias
353      * @param alias
354      * @return True if entry is deleted
355      */
356     public boolean deleteKeyFromTrustStore(String alias) {
357         try {
358             keyStore.deleteEntry(alias);
359         } catch (KeyStoreException e) {
360             logger.error("Cannot delete Key from keyTrustStore Instance", e);
361             return false;
362         }
363         return true;
364     }
365     /**
366      * Add a Certificate into the TrustStore based on its alias
367      * @param alias
368      * @param cert
369      * @return True if entry is added
370      */
371     public boolean setKeytoTrustStore(String alias, Certificate cert) {
372         try {
373             keyStore.setCertificateEntry(alias, cert);
374         } catch (KeyStoreException e) {
375             logger.error("Cannot add Certificate to keyTrustStore Instance", e);
376             return false;
377         }
378         return true;
379     }
380     /**
381      * Save the TrustStore to a file
382      * @param filename
383      * @return True if keyTrustStore is saved to file
384      */
385     public boolean saveTrustStore(String filename) {
386         FileOutputStream fos;
387         try {
388             fos = new FileOutputStream(filename);
389         } catch (FileNotFoundException e) {
390             logger.error("Cannot save to file keyTrustStore Instance", e);
391             return false;
392         }
393         try {
394             keyTrustStore.store(fos, getKeyTrustStorePassword());
395         } catch (KeyStoreException e) {
396             logger.error("Cannot save to file keyTrustStore Instance", e);
397             return false;
398         } catch (NoSuchAlgorithmException e) {
399             logger.error("Cannot save to file keyTrustStore Instance", e);
400             return false;
401         } catch (CertificateException e) {
402             logger.error("Cannot save to file keyTrustStore Instance", e);
403             return false;
404         } catch (IOException e) {
405             logger.error("Cannot save to file keyTrustStore Instance", e);
406             return false;
407         }
408         try {
409             fos.close();
410         } catch (IOException e) {
411         }
412         return true;
413     }
414     /**
415      * Load a certificate from a filename
416      * @param filename
417      * @return the X509 Certificate from filename
418      * @throws CertificateException
419      * @throws FileNotFoundException
420      */
421     public static Certificate loadX509Certificate(String filename)
422     throws CertificateException, FileNotFoundException {
423         CertificateFactory cf = CertificateFactory.getInstance("X.509");
424         FileInputStream in = new FileInputStream(filename);
425         return cf.generateCertificate(in);
426     }
427     /**
428      * @return the certificate Password
429      */
430     public char[] getCertificatePassword() {
431         if (keyPassword != null) {
432             return keyPassword.toCharArray();
433         }
434         return "secret".toCharArray();
435     }
436 
437     /**
438      * @return the KeyStore Password
439      */
440     public char[] getKeyStorePassword() {
441         if (keyStorePasswd != null) {
442             return keyStorePasswd.toCharArray();
443         }
444         return "secret".toCharArray();
445     }
446     /**
447      * @return the KeyTrustStore Password
448      */
449     public char[] getKeyTrustStorePassword() {
450         if (trustStorePasswd != null) {
451             return trustStorePasswd.toCharArray();
452         }
453         return "secret".toCharArray();
454     }
455     /**
456      * @return the secureTrustManagerFactory
457      */
458     public GgSecureTrustManagerFactory getSecureTrustManagerFactory() {
459         return secureTrustManagerFactory;
460     }
461     /**
462      * @return the keyManagerFactory
463      */
464     public KeyManagerFactory getKeyManagerFactory() {
465         return keyManagerFactory;
466     }
467 
468 }