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