KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > suberic > pooka > PookaEncryptionManager


1 package net.suberic.pooka;
2
3 import java.util.Map JavaDoc;
4 import java.util.HashMap JavaDoc;
5 import java.util.Set JavaDoc;
6
7 import java.io.File JavaDoc;
8 import java.io.FileInputStream JavaDoc;
9 import java.security.Key JavaDoc;
10 import java.security.KeyStoreException JavaDoc;
11 import java.security.GeneralSecurityException JavaDoc;
12 import java.util.HashSet JavaDoc;
13 import java.util.ArrayList JavaDoc;
14
15 import javax.mail.internet.*;
16 import javax.mail.*;
17
18 import net.suberic.crypto.*;
19 import net.suberic.util.VariableBundle;
20 import net.suberic.util.ValueChangeListener;
21
22 /**
23  * The EncryptionManager manages Pooka's encryption facilities. It's
24  * basically one-stop shopping for all of your email encryption needs.
25  */

26 public class PookaEncryptionManager implements ValueChangeListener {
27
28   String JavaDoc key;
29   VariableBundle sourceBundle;
30
31   EncryptionKeyManager pgpKeyMgr = null;
32
33   EncryptionKeyManager smimeKeyMgr = null;
34
35   char[] keyMgrPasswd = null;
36
37   Map JavaDoc cachedPrivateKeys = new HashMap JavaDoc();
38
39   Map JavaDoc cachedPublicKeys = new HashMap JavaDoc();
40
41   Map JavaDoc addressToPublicKeyMap = null;
42
43   boolean savePasswordsForSession = false;
44
45   boolean needsReload = false;
46
47   /**
48    * Creates an EncryptionManager using the given VariableBundle and
49    * key property.
50    */

51   public PookaEncryptionManager(VariableBundle pSourceBundle, String JavaDoc pKey) {
52     sourceBundle = pSourceBundle;
53     key = pKey;
54
55     // register this for listening to changes to the store filenames and the
56
// store passwords.
57
sourceBundle.addValueChangeListener(this, key + ".pgp.keyStore.private.filename");
58     sourceBundle.addValueChangeListener(this, key + ".pgp.keyStore.private.password");
59     sourceBundle.addValueChangeListener(this, key + ".pgp.keyStore.public.filename");
60
61     sourceBundle.addValueChangeListener(this, key + ".smime.keyStore.public.filename");
62     sourceBundle.addValueChangeListener(this, key + ".smime.keyStore.private.filename");
63     sourceBundle.addValueChangeListener(this, key + ".smime.keyStore.private.password");
64
65     sourceBundle.addValueChangeListener(this, key + ".savePasswordsForSession");
66
67     final VariableBundle fBundle = sourceBundle;
68     final String JavaDoc fKey = key;
69     Thread JavaDoc storeLoadingThread = new Thread JavaDoc(new Runnable JavaDoc() {
70     public void run() {
71       // load the given pgp and smime stores.
72
loadStores(fBundle, fKey);
73     }
74       });
75
76     storeLoadingThread.start();
77   }
78
79   /**
80    * Loads the stores.
81    */

82   public void loadStores(VariableBundle sourceBundle, String JavaDoc key) {
83     String JavaDoc pgpPublicFilename = sourceBundle.getProperty(key + ".pgp.keyStore.public.filename", "");
84
85     String JavaDoc pgpPrivateFilename = sourceBundle.getProperty(key + ".pgp.keyStore.private.filename", "");
86     String JavaDoc pgpPrivatePwString = sourceBundle.getProperty(key + ".pgp.keyStore.private.password", "");
87     if (!pgpPrivatePwString.equals(""))
88       pgpPrivatePwString = net.suberic.util.gui.propedit.PasswordEditorPane.descrambleString(pgpPrivatePwString);
89
90     // if either store is configured, try loading.
91
if (! (pgpPrivateFilename.equals("") && pgpPublicFilename.equals(""))) {
92       try {
93     EncryptionUtils pgpUtils = EncryptionManager.getEncryptionUtils("PGP");
94     if (pgpUtils != null) {
95       pgpKeyMgr = pgpUtils.createKeyManager();
96       try {
97         pgpKeyMgr.loadPrivateKeystore(new FileInputStream JavaDoc(new File JavaDoc(pgpPrivateFilename)), pgpPrivatePwString.toCharArray());
98       } catch (java.io.IOException JavaDoc fnfe) {
99         System.out.println("Error loading PGP private keystore from file " + pgpPrivateFilename + ": " + fnfe.getMessage());
100       } catch (java.security.GeneralSecurityException JavaDoc gse) {
101         System.out.println("Error loading PGP private keystore from file " + pgpPrivateFilename + ": " + gse.getMessage());
102       }
103       try {
104         pgpKeyMgr.loadPublicKeystore(new FileInputStream JavaDoc(new File JavaDoc(pgpPublicFilename)), null);
105       } catch (java.io.IOException JavaDoc fnfe) {
106         System.out.println("Error loading PGP public keystore from file " + pgpPublicFilename + ": " + fnfe.getMessage());
107       } catch (java.security.GeneralSecurityException JavaDoc gse) {
108         System.out.println("Error loading PGP private keystore from file " + pgpPublicFilename + ": " + gse.getMessage());
109       }
110     }
111       } catch (java.security.NoSuchProviderException JavaDoc nspe) {
112     System.out.println("Error loading PGP key store: " + nspe.getMessage());
113       } catch (Exception JavaDoc e) {
114     System.out.println("Error loading PGP key store: " + e.getMessage());
115       }
116     }
117
118     String JavaDoc smimePublicFilename = sourceBundle.getProperty(key + ".smime.keyStore.public.filename", "");
119
120     String JavaDoc smimePrivateFilename = sourceBundle.getProperty(key + ".smime.keyStore.private.filename", "");
121     String JavaDoc smimePrivatePwString = sourceBundle.getProperty(key + ".smime.keyStore.private.password", "");
122     if (!smimePrivatePwString.equals(""))
123       smimePrivatePwString = net.suberic.util.gui.propedit.PasswordEditorPane.descrambleString(smimePrivatePwString);
124
125     // if either store is configured, try loading.
126
if (! (smimePrivateFilename.equals("") && smimePublicFilename.equals(""))) {
127       try {
128     EncryptionUtils smimeUtils = EncryptionManager.getEncryptionUtils("S/MIME");
129     if (smimeUtils != null) {
130       smimeKeyMgr = smimeUtils.createKeyManager();
131       try {
132         smimeKeyMgr.loadPrivateKeystore(new FileInputStream JavaDoc(new File JavaDoc(smimePrivateFilename)), smimePrivatePwString.toCharArray());
133       } catch (java.security.GeneralSecurityException JavaDoc gse) {
134         System.out.println("Error loading S/MIME private keystore from file " + smimePrivateFilename + ": " + gse.getMessage());
135       } catch (java.io.IOException JavaDoc fnfe) {
136         System.out.println("Error loading S/MIME private keystore from file " + smimePrivateFilename + ": " + fnfe.getMessage());
137       }
138       
139       try {
140         smimeKeyMgr.loadPublicKeystore(new FileInputStream JavaDoc(new File JavaDoc(smimePublicFilename)), smimePrivatePwString.toCharArray());
141       } catch (java.io.IOException JavaDoc fnfe) {
142         System.out.println("Error loading S/MIME public keystore from file " + smimePublicFilename + ": " + fnfe.getMessage());
143       } catch (java.security.GeneralSecurityException JavaDoc gse) {
144         System.out.println("Error loading S/MIME private keystore from file " + smimePublicFilename + ": " + gse.getMessage());
145       }
146     }
147       } catch (java.security.NoSuchProviderException JavaDoc nspe) {
148     System.out.println("Error loading S/MIME key store: " + nspe.getMessage());
149       } catch (Exception JavaDoc e) {
150     System.out.println("Error loading S/MIME key store: " + e.getMessage());
151       }
152     }
153
154     savePasswordsForSession = Pooka.getProperty(key + ".savePasswordsForSession", "false").equalsIgnoreCase("true");
155     
156     cachedPrivateKeys = new HashMap JavaDoc();
157
158     cachedPublicKeys = new HashMap JavaDoc();
159
160     addressToPublicKeyMap = null;
161
162   }
163
164   /**
165    * As defined in net.suberic.util.ValueChangeListener.
166    *
167    */

168   public void valueChanged(String JavaDoc changedValue) {
169     if (changedValue.equals(key + ".savePasswordsForSession")) {
170       savePasswordsForSession = Pooka.getProperty(key + ".savePasswordsForSession", "false").equalsIgnoreCase("true");
171     } else {
172       // this is crazy.
173
needsReload = true;
174       javax.swing.SwingUtilities.invokeLater(new Runnable JavaDoc() {
175
176       public void run() {
177         if (needsReload) {
178           needsReload = false;
179           
180           Thread JavaDoc updateThread = new Thread JavaDoc(new Runnable JavaDoc() {
181           public void run() {
182             loadStores(sourceBundle, key);
183           }
184         });
185           
186           updateThread.start();
187         }
188       }
189     });
190     }
191   }
192   
193   
194   /**
195    * Adds the private key to the store.
196    */

197   public void addPrivateKey(String JavaDoc alias, Key JavaDoc privateKey, char[] passphrase, String JavaDoc type) throws GeneralSecurityException JavaDoc {
198     EncryptionKeyManager currentMgr = getKeyMgr(type);
199     if (currentMgr != null) {
200       currentMgr.setPrivateKeyEntry(alias, privateKey, passphrase);
201     } else {
202       throw new KeyStoreException JavaDoc(type + " KeyStore not initialized.");
203     }
204   }
205
206   /**
207    * Adds the public key to the store.
208    */

209   public void addPublicKey(String JavaDoc alias, Key JavaDoc publicKey, String JavaDoc type)
210   throws GeneralSecurityException JavaDoc {
211     
212     EncryptionKeyManager currentMgr = getKeyMgr(type);
213     if (currentMgr != null) {
214       currentMgr.setPublicKeyEntry(alias, publicKey);
215     } else {
216       throw new KeyStoreException JavaDoc(type + " KeyStore not initialized.");
217     }
218   }
219
220   /**
221    * Returns the private key(s) for the given email address.
222    */

223   public Key JavaDoc[] getPrivateKeys(String JavaDoc address) {
224     return getPrivateKeys(address, null);
225   }
226
227   /**
228    * Returns the private key(s) for the given email address and
229    * the given encryption type, or all matching keys if type == null.
230    */

231   public Key JavaDoc[] getPrivateKeys(String JavaDoc address, String JavaDoc type) {
232     return null;
233   }
234
235   /**
236    * Returns all private keys that have been cached.
237    */

238   public Key JavaDoc[] getCachedPrivateKeys() {
239     return (Key JavaDoc[]) cachedPrivateKeys.values().toArray(new Key JavaDoc[0]);
240   }
241   
242   /**
243    * Returns all available private key aliases.
244    */

245   public Set JavaDoc privateKeyAliases() throws java.security.KeyStoreException JavaDoc {
246     return privateKeyAliases(null);
247   }
248
249   /**
250    * Returns all available private key aliases for the give EncryptionType,
251    * or all available aliases if type is null.
252    */

253   public Set JavaDoc privateKeyAliases(String JavaDoc encryptionType) throws java.security.KeyStoreException JavaDoc {
254     if (encryptionType != null && encryptionType.equalsIgnoreCase(EncryptionManager.PGP)) {
255       if (pgpKeyMgr != null)
256     return new HashSet JavaDoc(pgpKeyMgr.privateKeyAliases());
257     } else if (encryptionType != null && encryptionType.equalsIgnoreCase(EncryptionManager.SMIME)) {
258       if (smimeKeyMgr != null) {
259     return new HashSet JavaDoc(smimeKeyMgr.privateKeyAliases());
260       }
261     } else {
262       // return both.
263
Set JavaDoc returnValue = new java.util.HashSet JavaDoc();
264       if (pgpKeyMgr != null) {
265     try {
266       returnValue.addAll(pgpKeyMgr.privateKeyAliases());
267     } catch (KeyStoreException JavaDoc kse) {
268       // FIXME ignore for now?
269
}
270       }
271       if (smimeKeyMgr != null) {
272     try {
273       returnValue.addAll(smimeKeyMgr.privateKeyAliases());
274     } catch (KeyStoreException JavaDoc kse) {
275       // FIXME ignore for now?
276
}
277       }
278
279       return returnValue;
280     }
281
282     return new HashSet JavaDoc();
283   }
284
285   /**
286    * Returns the Private key for the given alias.
287    */

288   public Key JavaDoc getPrivateKey(String JavaDoc alias) throws java.security.KeyStoreException JavaDoc, java.security.NoSuchAlgorithmException JavaDoc, java.security.UnrecoverableKeyException JavaDoc {
289     KeyStoreException JavaDoc caughtException = null;
290
291     // first check to see if this is in the cache.
292
Key JavaDoc cachedKey = (Key JavaDoc) cachedPrivateKeys.get(alias);
293     if (cachedKey != null)
294       return cachedKey;
295
296     if (pgpKeyMgr != null || smimeKeyMgr != null) {
297
298       // check to see if this exists anywhere.
299
if (pgpKeyMgr != null) {
300     try {
301       if (pgpKeyMgr.containsPrivateKeyAlias(alias)) {
302         Key JavaDoc returnValue = pgpKeyMgr.getPrivateKey(alias, null);
303         cachedPrivateKeys.put(alias, returnValue);
304         return returnValue;
305       }
306     } catch (KeyStoreException JavaDoc kse) {
307       caughtException = kse;
308     }
309     
310       }
311       
312       if (smimeKeyMgr!= null) {
313     try {
314       if (smimeKeyMgr.containsPrivateKeyAlias(alias)) {
315         Key JavaDoc returnValue = smimeKeyMgr.getPrivateKey(alias, null);
316         cachedPrivateKeys.put(alias, returnValue);
317         return returnValue;
318       }
319     } catch (KeyStoreException JavaDoc kse) {
320       if (caughtException == null)
321         caughtException = kse;
322     }
323     
324       }
325     }
326     
327     if (caughtException != null)
328       throw caughtException;
329
330     return null;
331   }
332
333   /**
334    * Returns the Private key for the given alias.
335    */

336   public Key JavaDoc getPrivateKey(String JavaDoc alias, char[] password) throws java.security.KeyStoreException JavaDoc, java.security.NoSuchAlgorithmException JavaDoc, java.security.UnrecoverableKeyException JavaDoc {
337
338     KeyStoreException JavaDoc caughtException = null;
339
340     // first check to see if this is in the cache.
341
Key JavaDoc cachedKey = (Key JavaDoc) cachedPrivateKeys.get(alias);
342     if (cachedKey != null)
343       return cachedKey;
344
345     Key JavaDoc returnValue = null;
346     if (pgpKeyMgr != null) {
347       try {
348     returnValue = pgpKeyMgr.getPrivateKey(alias, password);
349       } catch (KeyStoreException JavaDoc kse) {
350       caughtException = kse;
351       }
352     }
353
354     if (returnValue == null && smimeKeyMgr != null) {
355       try {
356     returnValue = smimeKeyMgr.getPrivateKey(alias, password);
357       } catch (KeyStoreException JavaDoc kse) {
358     if (caughtException == null)
359       caughtException = kse;
360       }
361     }
362
363     if (returnValue != null) {
364       cachedPrivateKeys.put(alias, returnValue);
365     }
366
367     if (returnValue == null && caughtException != null)
368       throw caughtException;
369
370     return returnValue;
371   }
372
373   /**
374    * Returns the Public key for the given alias.
375    */

376   public Key JavaDoc getPublicKey(String JavaDoc alias) throws java.security.KeyStoreException JavaDoc, java.security.NoSuchAlgorithmException JavaDoc, java.security.UnrecoverableKeyException JavaDoc {
377     Key JavaDoc returnValue = null;
378     if (pgpKeyMgr != null) {
379       try {
380     returnValue = pgpKeyMgr.getPublicKey(alias);
381       } catch (KeyStoreException JavaDoc kse) {
382     // FIXME ignore for now?
383
}
384     }
385
386     if (returnValue == null && smimeKeyMgr != null) {
387       try {
388     returnValue = smimeKeyMgr.getPublicKey(alias);
389       } catch (KeyStoreException JavaDoc kse) {
390     // FIXME ignore for now?
391
}
392     }
393
394     return returnValue;
395   }
396
397   /**
398    * Returns the public key(s) for the given email address.
399    */

400   public Key JavaDoc[] getPublicKeys(String JavaDoc address) throws java.security.KeyStoreException JavaDoc, java.security.NoSuchAlgorithmException JavaDoc, java.security.UnrecoverableKeyException JavaDoc {
401     return getPublicKeys(address, null);
402   }
403
404   /**
405    * Returns the public key(s) for the given email address that match
406    * the given encryption type, or all matching keys if type == null.
407    */

408   public Key JavaDoc[] getPublicKeys(String JavaDoc address, String JavaDoc type) throws java.security.KeyStoreException JavaDoc, java.security.NoSuchAlgorithmException JavaDoc, java.security.UnrecoverableKeyException JavaDoc {
409     if (addressToPublicKeyMap == null) {
410       sortPublicKeys();
411     }
412
413     ArrayList JavaDoc list = (ArrayList JavaDoc) addressToPublicKeyMap.get(address);
414     if (list == null)
415       return new Key JavaDoc[0];
416     else if (type == null) {
417       return (Key JavaDoc[]) list.toArray(new Key JavaDoc[0]);
418     } else {
419       ArrayList JavaDoc sortedList = new ArrayList JavaDoc();
420       java.util.Iterator JavaDoc iter = list.iterator();
421       while (iter.hasNext()) {
422     EncryptionKey current = (EncryptionKey) iter.next();
423     try {
424       if (current.getEncryptionUtils().getType() == type) {
425         sortedList.add(current);
426       }
427     } catch (Exception JavaDoc e) {
428     }
429       }
430
431       return (Key JavaDoc[]) sortedList.toArray(new Key JavaDoc[0]);
432     }
433   }
434
435   /**
436    * Sorts all available public keys by associated address.
437    */

438   private synchronized void sortPublicKeys() throws java.security.KeyStoreException JavaDoc, java.security.NoSuchAlgorithmException JavaDoc, java.security.UnrecoverableKeyException JavaDoc {
439     if (addressToPublicKeyMap == null) {
440       addressToPublicKeyMap = new HashMap JavaDoc();
441       Set JavaDoc aliases = publicKeyAliases();
442       java.util.Iterator JavaDoc iter = aliases.iterator();
443       while (iter.hasNext()) {
444     Key JavaDoc current = getPublicKey((String JavaDoc) iter.next());
445
446     if (current instanceof EncryptionKey) {
447       String JavaDoc[] assocAddresses = ((EncryptionKey) current).getAssociatedAddresses();
448       for (int i = 0; assocAddresses != null && i < assocAddresses.length; i++) {
449         String JavaDoc address = assocAddresses[i];
450         ArrayList JavaDoc matches = (ArrayList JavaDoc) addressToPublicKeyMap.get(address);
451         if (matches != null) {
452           if (! matches.contains(current))
453           matches.add(current);
454         } else {
455           matches = new ArrayList JavaDoc();
456           matches.add(current);
457           addressToPublicKeyMap.put(address, matches);
458         }
459       }
460     }
461       }
462     }
463   }
464
465   /**
466    * Returns all available public key aliases.
467    */

468   public Set JavaDoc publicKeyAliases() throws java.security.KeyStoreException JavaDoc {
469     return publicKeyAliases(null);
470   }
471
472   /**
473    * Returns available public key aliases for the given encryption type, or
474    * all available aliases if null.
475    */

476   public Set JavaDoc publicKeyAliases(String JavaDoc encryptionType) throws java.security.KeyStoreException JavaDoc {
477
478     if (encryptionType != null && encryptionType.equalsIgnoreCase(EncryptionManager.PGP)) {
479       if (pgpKeyMgr != null)
480     return new HashSet JavaDoc(pgpKeyMgr.publicKeyAliases());
481     } else if (encryptionType != null && encryptionType.equalsIgnoreCase(EncryptionManager.SMIME)) {
482       if (smimeKeyMgr != null) {
483     return new HashSet JavaDoc(smimeKeyMgr.publicKeyAliases());
484       }
485     } else {
486       // return both.
487
Set JavaDoc returnValue = new java.util.HashSet JavaDoc();
488       if (pgpKeyMgr != null) {
489     try {
490       returnValue.addAll(pgpKeyMgr.publicKeyAliases());
491     } catch (KeyStoreException JavaDoc kse) {
492       // FIXME ignore for now?
493
}
494       }
495       if (smimeKeyMgr != null) {
496     try {
497       returnValue.addAll(smimeKeyMgr.publicKeyAliases());
498     } catch (KeyStoreException JavaDoc kse) {
499       // FIXME ignore for now?
500
}
501       }
502       
503       return returnValue;
504     }
505
506     return new HashSet JavaDoc();
507
508   }
509
510   /**
511    * Encrypts to given message. Actually checks all of the recipients
512    * configured to see if we have a key for each one.
513    */

514   public MimeMessage encryptMessage(MimeMessage mMsg) throws MessagingException, java.security.GeneralSecurityException JavaDoc, java.io.IOException JavaDoc {
515     
516     // if we don't have a key, see if we can get a default.
517
Key JavaDoc key = null;
518     Address[] recipients = mMsg.getRecipients(Message.RecipientType.TO);
519     for (int i = 0; key == null && i < recipients.length; i++) {
520       if (recipients[i] instanceof InternetAddress) {
521     String JavaDoc inetAddr = ((InternetAddress) recipients[i]).getAddress();
522     Key JavaDoc[] matchingKeys = getPublicKeys(inetAddr);
523     if (matchingKeys != null) {
524       for (int j = 0; key != null && j < matchingKeys.length; j++) {
525         key = matchingKeys[j];
526       }
527     }
528       }
529     }
530     
531     return encryptMessage(mMsg, key);
532   }
533
534   /**
535    * Encrypts the given message. If there's no key, return null.
536    */

537   public MimeMessage encryptMessage(MimeMessage mMsg, Key JavaDoc key)
538     throws MessagingException, java.security.GeneralSecurityException JavaDoc, java.io.IOException JavaDoc {
539     if (key != null) {
540       if (key instanceof EncryptionKey) {
541     return ((EncryptionKey) key).getEncryptionUtils().encryptMessage(Pooka.getDefaultSession(), mMsg, key);
542       } else {
543     return EncryptionManager.getEncryptionUtils("PGP").encryptMessage(Pooka.getDefaultSession(), mMsg, key);
544       }
545       
546     }
547     return mMsg;
548   }
549
550   /**
551    * Signs the given message.
552    */

553   public MimeMessage signMessage(MimeMessage mMsg, UserProfile profile, Key JavaDoc key)
554     throws MessagingException, java.io.IOException JavaDoc, java.security.GeneralSecurityException JavaDoc {
555     if (key == null && profile != null) {
556       key = profile.getEncryptionKey();
557     }
558     
559     if (key == null) {
560       // get user input
561
}
562     
563     if (key != null) {
564       if (key instanceof net.suberic.crypto.EncryptionKey) {
565     return ((EncryptionKey) key).getEncryptionUtils().signMessage(Pooka.getDefaultSession(), mMsg, key);
566       } else {
567     return EncryptionManager.getEncryptionUtils("PGP").signMessage(Pooka.getDefaultSession(), mMsg, key);
568       }
569     } else {
570       return mMsg;
571     }
572   }
573
574   /**
575    * Returns the EncryptionKeyManager for this type.
576    */

577   EncryptionKeyManager getKeyMgr(String JavaDoc type) {
578     if (type == EncryptionManager.PGP)
579       return pgpKeyMgr;
580     else if (type == EncryptionManager.SMIME)
581       return smimeKeyMgr;
582     else
583       return null;
584   }
585 }
586
Popular Tags