1:
37:
38:
39: package ;
40:
41: import ;
42: import ;
43: import ;
44: import ;
45: import ;
46: import ;
47: import ;
48: import ;
49: import ;
50:
51: import ;
52: import ;
53: import ;
54: import ;
55: import ;
56: import ;
57: import ;
58: import ;
59: import ;
60: import ;
61: import ;
62: import ;
63: import ;
64: import ;
65: import ;
66: import ;
67: import ;
68: import ;
69: import ;
70:
71: import ;
72:
73:
77: public class GnuKeyring
78: extends KeyStoreSpi
79: {
80: private static final Logger log = Logger.getLogger(GnuKeyring.class.getName());
81: private static final String NOT_LOADED = "not loaded";
82:
83:
84: private boolean loaded;
85:
86: private IPrivateKeyring privateKR;
87:
88: private IPublicKeyring publicKR;
89:
90:
91:
92: public Enumeration engineAliases()
93: {
94: if (Configuration.DEBUG)
95: log.entering(this.getClass().getName(), "engineAliases");
96: ensureLoaded();
97: Enumeration result;
98: if (privateKR == null)
99: result = Collections.enumeration(Collections.EMPTY_SET);
100: else
101: {
102: Set aliases = new HashSet();
103: for (Enumeration e = privateKR.aliases(); e.hasMoreElements();)
104: {
105: String alias = (String) e.nextElement();
106: if (alias != null)
107: {
108: alias = alias.trim();
109: if (alias.length() > 0)
110: {
111: if (Configuration.DEBUG)
112: log.fine("Adding alias (from private keyring): " + alias);
113: aliases.add(alias);
114: }
115: }
116: }
117: for (Enumeration e = publicKR.aliases(); e.hasMoreElements();)
118: {
119: String alias = (String) e.nextElement();
120: if (alias != null)
121: {
122: alias = alias.trim();
123: if (alias.length() > 0)
124: {
125: if (Configuration.DEBUG)
126: log.fine("Adding alias (from public keyring): " + alias);
127: aliases.add(alias);
128: }
129: }
130: }
131: if (Configuration.DEBUG)
132: log.fine("Will enumerate: " + aliases);
133: result = Collections.enumeration(aliases);
134: }
135: if (Configuration.DEBUG)
136: log.exiting(this.getClass().getName(), "engineAliases");
137: return result;
138: }
139:
140: public boolean engineContainsAlias(String alias)
141: {
142: if (Configuration.DEBUG)
143: log.entering(this.getClass().getName(), "engineContainsAlias", alias);
144: ensureLoaded();
145: boolean inPrivateKR = privateKR.containsAlias(alias);
146: if (Configuration.DEBUG)
147: log.fine("inPrivateKR=" + inPrivateKR);
148: boolean inPublicKR = publicKR.containsAlias(alias);
149: if (Configuration.DEBUG)
150: log.fine("inPublicKR=" + inPublicKR);
151: boolean result = inPrivateKR || inPublicKR;
152: if (Configuration.DEBUG)
153: log.exiting(this.getClass().getName(), "engineContainsAlias",
154: Boolean.valueOf(result));
155: return result;
156: }
157:
158: public void engineDeleteEntry(String alias)
159: {
160: if (Configuration.DEBUG)
161: log.entering(this.getClass().getName(), "engineDeleteEntry", alias);
162: ensureLoaded();
163: if (privateKR.containsAlias(alias))
164: privateKR.remove(alias);
165: else if (publicKR.containsAlias(alias))
166: publicKR.remove(alias);
167: else if (Configuration.DEBUG)
168: log.fine("Unknwon alias: " + alias);
169: if (Configuration.DEBUG)
170: log.exiting(this.getClass().getName(), "engineDeleteEntry");
171: }
172:
173: public Certificate engineGetCertificate(String alias)
174: {
175: if (Configuration.DEBUG)
176: log.entering(this.getClass().getName(), "engineGetCertificate", alias);
177: ensureLoaded();
178: Certificate result = publicKR.getCertificate(alias);
179: if (Configuration.DEBUG)
180: log.exiting(this.getClass().getName(), "engineGetCertificate", result);
181: return result;
182: }
183:
184: public String engineGetCertificateAlias(Certificate cert)
185: {
186: if (Configuration.DEBUG)
187: log.entering(this.getClass().getName(), "engineGetCertificateAlias", cert);
188: ensureLoaded();
189: String result = null;
190: for (Enumeration aliases = publicKR.aliases(); aliases.hasMoreElements();)
191: {
192: String alias = (String) aliases.nextElement();
193: Certificate cert2 = publicKR.getCertificate(alias);
194: if (cert.equals(cert2))
195: {
196: result = alias;
197: break;
198: }
199: }
200: if (Configuration.DEBUG)
201: log.exiting(this.getClass().getName(), "engineGetCertificateAlias", result);
202: return result;
203: }
204:
205: public void engineSetCertificateEntry(String alias, Certificate cert)
206: throws KeyStoreException
207: {
208: if (Configuration.DEBUG)
209: log.entering(this.getClass().getName(), "engineSetCertificateEntry",
210: new Object[] { alias, cert });
211: ensureLoaded();
212: if (privateKR.containsAlias(alias))
213: throw new KeyStoreException("Alias [" + alias
214: + "] already exists and DOES NOT identify a "
215: + "Trusted Certificate Entry");
216: if (publicKR.containsCertificate(alias))
217: {
218: if (Configuration.DEBUG)
219: log.fine("Public keyring already contains Alias [" + alias
220: + "]. Will remove it");
221: publicKR.remove(alias);
222: }
223: publicKR.putCertificate(alias, cert);
224: if (Configuration.DEBUG)
225: log.exiting(this.getClass().getName(), "engineSetCertificateEntry");
226: }
227:
228: public Certificate[] engineGetCertificateChain(String alias)
229: {
230: if (Configuration.DEBUG)
231: log.entering(this.getClass().getName(), "engineGetCertificateChain", alias);
232: ensureLoaded();
233: Certificate[] result = privateKR.getCertPath(alias);
234: if (Configuration.DEBUG)
235: log.exiting(this.getClass().getName(), "engineGetCertificateChain", result);
236: return result;
237: }
238:
239: public Date engineGetCreationDate(String alias)
240: {
241: if (Configuration.DEBUG)
242: log.entering(this.getClass().getName(), "engineGetCreationDate", alias);
243: ensureLoaded();
244: Date result = getCreationDate(alias, privateKR);
245: if (result == null)
246: result = getCreationDate(alias, publicKR);
247:
248: if (Configuration.DEBUG)
249: log.exiting(this.getClass().getName(), "engineGetCreationDate", result);
250: return result;
251: }
252:
253: public Key engineGetKey(String alias, char[] password)
254: throws UnrecoverableKeyException
255: {
256: if (Configuration.DEBUG)
257: log.entering(this.getClass().getName(), "engineGetKey", alias);
258: ensureLoaded();
259: Key result = null;
260: if (password == null)
261: {
262: if (privateKR.containsPublicKey(alias))
263: result = privateKR.getPublicKey(alias);
264: }
265: else if (privateKR.containsPrivateKey(alias))
266: result = privateKR.getPrivateKey(alias, password);
267:
268: if (Configuration.DEBUG)
269: log.exiting(this.getClass().getName(), "engineGetKey",
270: result == null ? "null" : result.getClass().getName());
271: return result;
272: }
273:
274: public void engineSetKeyEntry(String alias, Key key, char[] password,
275: Certificate[] chain)
276: throws KeyStoreException
277: {
278: if (Configuration.DEBUG)
279: log.entering(this.getClass().getName(), "engineSetKeyEntry",
280: new Object[] { alias, key.getClass().getName(), chain });
281: ensureLoaded();
282: if (publicKR.containsAlias(alias))
283: throw new KeyStoreException("Alias [" + alias
284: + "] already exists and DOES NOT identify a "
285: + "Key Entry");
286: if (key instanceof PublicKey)
287: {
288: privateKR.remove(alias);
289: PublicKey pk = (PublicKey) key;
290: privateKR.putPublicKey(alias, pk);
291: }
292: else
293: {
294: if (! (key instanceof PrivateKey) && ! (key instanceof SecretKey))
295: throw new KeyStoreException("cannot store keys of type "
296: + key.getClass().getName());
297: privateKR.remove(alias);
298: privateKR.putCertPath(alias, chain);
299: if (Configuration.DEBUG)
300: log.fine("About to put private key in keyring...");
301: privateKR.putPrivateKey(alias, key, password);
302: }
303: if (Configuration.DEBUG)
304: log.exiting(this.getClass().getName(), "engineSetKeyEntry");
305: }
306:
307: public void engineSetKeyEntry(String alias, byte[] key, Certificate[] chain)
308: throws KeyStoreException
309: {
310: KeyStoreException x = new KeyStoreException("method not supported");
311: if (Configuration.DEBUG)
312: log.throwing(this.getClass().getName(), "engineSetKeyEntry(3)", x);
313: throw x;
314: }
315:
316: public boolean engineIsCertificateEntry(String alias)
317: {
318: if (Configuration.DEBUG)
319: log.entering(this.getClass().getName(), "engineIsCertificateEntry", alias);
320: ensureLoaded();
321: boolean result = publicKR.containsCertificate(alias);
322: if (Configuration.DEBUG)
323: log.exiting(this.getClass().getName(), "engineIsCertificateEntry",
324: Boolean.valueOf(result));
325: return result;
326: }
327:
328: public boolean engineIsKeyEntry(String alias)
329: {
330: if (Configuration.DEBUG)
331: log.entering(this.getClass().getName(), "engineIsKeyEntry", alias);
332: ensureLoaded();
333: boolean result = privateKR.containsPublicKey(alias)
334: || privateKR.containsPrivateKey(alias);
335: if (Configuration.DEBUG)
336: log.exiting(this.getClass().getName(), "engineIsKeyEntry",
337: Boolean.valueOf(result));
338: return result;
339: }
340:
341: public void engineLoad(InputStream in, char[] password) throws IOException
342: {
343: if (Configuration.DEBUG)
344: log.entering(this.getClass().getName(), "engineLoad");
345: if (in != null)
346: {
347: if (! in.markSupported())
348: in = new BufferedInputStream(in);
349:
350: loadPrivateKeyring(in, password);
351: loadPublicKeyring(in, password);
352: }
353: else
354: createNewKeyrings();
355:
356: loaded = true;
357: if (Configuration.DEBUG)
358: log.exiting(this.getClass().getName(), "engineLoad");
359: }
360:
361: public void engineStore(OutputStream out, char[] password) throws IOException
362: {
363: if (Configuration.DEBUG)
364: log.entering(this.getClass().getName(), "engineStore");
365: ensureLoaded();
366: HashMap attr = new HashMap();
367: attr.put(IKeyring.KEYRING_DATA_OUT, out);
368: attr.put(IKeyring.KEYRING_PASSWORD, password);
369:
370: privateKR.store(attr);
371: publicKR.store(attr);
372: if (Configuration.DEBUG)
373: log.exiting(this.getClass().getName(), "engineStore");
374: }
375:
376: public int engineSize()
377: {
378: if (Configuration.DEBUG)
379: log.entering(this.getClass().getName(), "engineSize");
380: int result = 0;
381: for (Enumeration e = engineAliases(); e.hasMoreElements(); result++)
382: e.nextElement();
383:
384: if (Configuration.DEBUG)
385: log.exiting(this.getClass().getName(), "engineSize", Integer.valueOf(result));
386: return result;
387: }
388:
389:
395: private void ensureLoaded()
396: {
397: if (! loaded)
398: throw new IllegalStateException(NOT_LOADED);
399: }
400:
401:
409: private void loadPrivateKeyring(InputStream in, char[] password)
410: throws MalformedKeyringException, IOException
411: {
412: if (Configuration.DEBUG)
413: log.entering(this.getClass().getName(), "loadPrivateKeyring");
414: in.mark(5);
415: for (int i = 0; i < 4; i++)
416: if (in.read() != Registry.GKR_MAGIC[i])
417: throw new MalformedKeyringException("incorrect magic");
418:
419: int usage = in.read();
420: in.reset();
421: if (usage != GnuPrivateKeyring.USAGE)
422: throw new MalformedKeyringException(
423: "Was expecting a private keyring but got a wrong USAGE: "
424: + Integer.toBinaryString(usage));
425: HashMap attr = new HashMap();
426: attr.put(IKeyring.KEYRING_DATA_IN, in);
427: attr.put(IKeyring.KEYRING_PASSWORD, password);
428: privateKR = new GnuPrivateKeyring();
429: privateKR.load(attr);
430: if (Configuration.DEBUG)
431: log.exiting(this.getClass().getName(), "loadPrivateKeyring");
432: }
433:
434:
442: private void loadPublicKeyring(InputStream in, char[] password)
443: throws MalformedKeyringException, IOException
444: {
445: if (Configuration.DEBUG)
446: log.entering(this.getClass().getName(), "loadPublicKeyring");
447: in.mark(5);
448: for (int i = 0; i < 4; i++)
449: if (in.read() != Registry.GKR_MAGIC[i])
450: throw new MalformedKeyringException("incorrect magic");
451:
452: int usage = in.read();
453: in.reset();
454: if (usage != GnuPublicKeyring.USAGE)
455: throw new MalformedKeyringException(
456: "Was expecting a public keyring but got a wrong USAGE: "
457: + Integer.toBinaryString(usage));
458: HashMap attr = new HashMap();
459: attr.put(IKeyring.KEYRING_DATA_IN, in);
460: attr.put(IKeyring.KEYRING_PASSWORD, password);
461: publicKR = new GnuPublicKeyring();
462: publicKR.load(attr);
463: if (Configuration.DEBUG)
464: log.exiting(this.getClass().getName(), "loadPublicKeyring");
465: }
466:
467:
476: private Date getCreationDate(String alias, IKeyring keyring)
477: {
478: if (Configuration.DEBUG)
479: log.entering(this.getClass().getName(), "getCreationDate",
480: new Object[] { alias, keyring });
481: Date result = null;
482: if (keyring != null)
483: for (Iterator it = keyring.get(alias).iterator(); it.hasNext();)
484: {
485: Object o = it.next();
486: if (o instanceof PrimitiveEntry)
487: {
488: result = ((PrimitiveEntry) o).getCreationDate();
489: break;
490: }
491: }
492: if (Configuration.DEBUG)
493: log.exiting(this.getClass().getName(), "getCreationDate", result);
494: return result;
495: }
496:
497:
498: private void createNewKeyrings()
499: {
500: if (Configuration.DEBUG)
501: log.entering(this.getClass().getName(), "createNewKeyrings");
502: privateKR = new GnuPrivateKeyring("HMAC-SHA-1", 20, "AES", "OFB", 16);
503: publicKR = new GnuPublicKeyring("HMAC-SHA-1", 20);
504: if (Configuration.DEBUG)
505: log.exiting(this.getClass().getName(), "createNewKeyrings");
506: }
507: }