2
* $Id: KeyChain.java,v 1.4 2005/10/26 11:44:29 kleopatra Exp $
4
* Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
5
* Santa Clara, California 95054, U.S.A. All rights reserved.
7
* This library is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU Lesser General Public
9
* License as published by the Free Software Foundation; either
10
* version 2.1 of the License, or (at your option) any later version.
12
* This library is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
* Lesser General Public License for more details.
17
* You should have received a copy of the GNU Lesser General Public
18
* License along with this library; if not, write to the Free Software
19
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
package org.jdesktop.swingx.auth;
23
import java.io.EOFException;
25
import java.io.FileInputStream;
26
import java.io.FileOutputStream;
27
import java.io.IOException;
28
import java.io.InputStream;
29
import java.io.OutputStream;
30
import java.security.KeyStore;
31
import java.security.KeyStoreException;
32
import java.security.NoSuchAlgorithmException;
33
import java.security.UnrecoverableEntryException;
34
import java.security.cert.CertificateException;
35
import java.util.logging.Level;
36
import java.util.logging.Logger;
38
import javax.crypto.spec.SecretKeySpec;
41
* <b>KeyChain</b> is a class that implements the "KeyChain" concept.
42
* Fundamentally, it allows you to store multiple keys/credentials
43
* in a central password store. Access to this central store is
44
* controlled through a master password. This mechanism is used in
45
* many popular client applications where you need to store credentials
46
* for multiple servers/accounts. The actual store for the KeyStore
47
* can be any OutputStream and it can work in the webstart sandbox
51
* To contstruct a <b>KeyChain</b>, you need to pass in an InputStream to the
52
* store and it will initialize the KeyStore from the InputStream.
53
* You can add and remove entries any time once you have an instance of
54
* KeyChain. To persist the KeyChain and reflect any changes, you need to
55
* call <b>store</b> method with an OutputStream.
60
public class KeyChain {
61
private static final Logger LOG = Logger
62
.getLogger(KeyChain.class.getName());
64
private KeyStore store;
66
private char[] masterPassword;
69
* Creates an instance of KeyChain and initializes the store
70
* from the InputStream.
72
* @param masterPassword
76
public KeyChain(char[] masterPassword, InputStream inputStream)
78
this.masterPassword = masterPassword;
81
store = KeyStore.getInstance("JCEKS");
82
store.load(inputStream, masterPassword);
84
} catch (KeyStoreException ex) {
85
LOG.log(Level.WARNING, "", ex);
86
} catch (CertificateException ex) {
87
LOG.log(Level.WARNING, "", ex);
88
} catch (NoSuchAlgorithmException ex) {
89
LOG.log(Level.WARNING, "", ex);
90
} catch (EOFException ex) {
91
LOG.log(Level.WARNING, "", ex);
97
* Fetches the password for a given account/user and server.
100
* @return <code>null</code> if no password could be obtained, the password
103
public String getPassword(String user, String server) {
107
KeyStore.SecretKeyEntry entry2 = (KeyStore.SecretKeyEntry) store
108
.getEntry(user + "@" + server,
109
new KeyStore.PasswordProtection(masterPassword));
110
return new String(entry2.getSecretKey().getEncoded());
111
} catch (KeyStoreException ex) {
112
LOG.log(Level.WARNING, "", ex);
113
} catch (UnrecoverableEntryException ex) {
114
LOG.log(Level.WARNING, "", ex);
115
} catch (NoSuchAlgorithmException ex) {
116
LOG.log(Level.WARNING, "", ex);
123
* Adds a password to the KeyChain for a given account/user and server.
129
public void addPassword(String user, String server, char[] password)
131
String pass = new String(password);
132
SecretKeySpec passwordKey = new SecretKeySpec(pass.getBytes(), "JCEKS");
133
KeyStore.SecretKeyEntry entry = new KeyStore.SecretKeyEntry(passwordKey);
135
store.setEntry(user + "@" + server, entry,
136
new KeyStore.PasswordProtection(masterPassword));
137
} catch (KeyStoreException e) {
138
LOG.log(Level.WARNING, "", e);
143
* Removes a password for a given account/user and server.
148
public void removePassword(String user, String server) {
150
store.deleteEntry(user + "@" + server);
151
} catch (KeyStoreException e) {
152
LOG.log(Level.WARNING, "", e);
157
* Persists the KeyChain to an OutputStream
160
* @throws IOException
163
public void store(OutputStream ostream) throws IOException {
165
store.store(ostream, masterPassword);
166
} catch (KeyStoreException ex) {
167
LOG.log(Level.WARNING, "", ex);
168
} catch (CertificateException ex) {
169
LOG.log(Level.WARNING, "", ex);
170
} catch (NoSuchAlgorithmException ex) {
171
LOG.log(Level.WARNING, "", ex);
176
public static void main(String[] args) {
178
File file = new File("c:\\test.txt");
180
if (!file.exists()) {
181
file.createNewFile();
184
fis = new FileInputStream(file);
186
KeyChain kc = new KeyChain("test".toCharArray(), fis);
187
kc.addPassword("bino", "sun-ds.sfbay", "test123".toCharArray());
189
+ kc.getPassword("bino", "sun-ds.sfbay"));
191
LOG.fine("More testing :");
192
for (int i = 0; i < 100; i++) {
193
kc.addPassword("" + i, "sun-ds.sfbay", ("" + i).toCharArray());
195
for (int i = 0; i < 100; i++) {
196
LOG.fine("key =" + i + " pass ="
197
+ kc.getPassword("" + i, "sun-ds.sfbay"));
199
kc.store(new FileOutputStream(file));
200
} catch (Exception e) {
201
LOG.log(Level.WARNING, "", e);