001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.security.srp;
023:
024: import java.io.File;
025: import java.io.FileInputStream;
026: import java.io.FileOutputStream;
027: import java.io.IOException;
028: import java.io.ObjectInputStream;
029: import java.io.ObjectOutputStream;
030: import java.math.BigInteger;
031: import java.security.KeyException;
032: import java.security.NoSuchAlgorithmException;
033: import java.util.Collections;
034: import java.util.HashMap;
035: import java.util.Map;
036:
037: import org.jboss.logging.Logger;
038: import org.jboss.security.Util;
039: import org.jboss.security.srp.SRPConf;
040: import org.jboss.security.srp.SRPVerifierStore;
041: import org.jboss.security.srp.SRPVerifierStore.VerifierInfo;
042:
043: /** A simple implementation of the SRPVerifierStore that uses a
044: file store made up of VerifierInfo serialized objects. Users and
045: be added or removed using the addUser and delUser methods. User passwords
046: are never stored in plaintext either in memory or in the serialized file.
047: Note that usernames and passwords are logged when a user is added
048: via the addUser operation. This is a development class and its use in
049: a production environment is not advised.
050:
051: @see #addUser(String, String)
052: @see #delUser(String)
053:
054: @author Scott.Stark@jboss.org
055: @version $Revision: 57210 $
056: */
057: public class SerialObjectStore implements SRPVerifierStore {
058: private static Logger log = Logger
059: .getLogger(SerialObjectStore.class);
060: private Map infoMap;
061: private BigInteger g;
062: private BigInteger N;
063:
064: /** Create an in memory store and load any VerifierInfo found in
065: ./SerialObjectStore.ser if it exists.
066: */
067: public SerialObjectStore() throws IOException {
068: this (null);
069: }
070:
071: /** Create an in memory store and load any VerifierInfo found in
072: the storeFile archive if it exists.
073: */
074: public SerialObjectStore(File storeFile) throws IOException {
075: if (storeFile == null)
076: storeFile = new File("SerialObjectStore.ser");
077: if (storeFile.exists() == true) {
078: FileInputStream fis = new FileInputStream(storeFile);
079: ObjectInputStream ois = new ObjectInputStream(fis);
080: try {
081: infoMap = (Map) ois.readObject();
082: } catch (ClassNotFoundException e) {
083: }
084: ois.close();
085: fis.close();
086: } else {
087: infoMap = Collections.synchronizedMap(new HashMap());
088: }
089:
090: try {
091: Util.init();
092: } catch (NoSuchAlgorithmException e) {
093: e.printStackTrace();
094: throw new IOException(
095: "Failed to initialzed security utils: "
096: + e.getMessage());
097: }
098: N = SRPConf.getDefaultParams().N();
099: g = SRPConf.getDefaultParams().g();
100: log.trace("N: " + Util.tob64(N.toByteArray()));
101: log.trace("g: " + Util.tob64(g.toByteArray()));
102: byte[] hn = Util.newDigest().digest(N.toByteArray());
103: log.trace("H(N): " + Util.tob64(hn));
104: byte[] hg = Util.newDigest().digest(g.toByteArray());
105: log.trace("H(g): " + Util.tob64(hg));
106: }
107:
108: // --- Begin SRPVerifierStore interface methods
109: public VerifierInfo getUserVerifier(String username)
110: throws KeyException, IOException {
111: VerifierInfo info = null;
112: if (infoMap != null)
113: info = (VerifierInfo) infoMap.get(username);
114: if (info == null)
115: throw new KeyException("username: " + username
116: + " not found");
117: return info;
118: }
119:
120: public void setUserVerifier(String username, VerifierInfo info) {
121: infoMap.put(username, info);
122: }
123:
124: public void verifyUserChallenge(String username, Object auxChallenge)
125: throws SecurityException {
126: throw new SecurityException("verifyUserChallenge not supported");
127: }
128:
129: // --- End SRPVerifierStore interface methods
130:
131: /** Save the current in memory map of VerifierInfo to the indicated
132: storeFile by simply serializing the map to the file.
133: */
134: public void save(File storeFile) throws IOException {
135: FileOutputStream fos = new FileOutputStream(storeFile);
136: ObjectOutputStream oos = new ObjectOutputStream(fos);
137: synchronized (infoMap) {
138: oos.writeObject(infoMap);
139: }
140: oos.close();
141: fos.close();
142: }
143:
144: public void addUser(String username, String password) {
145: log.trace("addUser, username='" + username + "', password='"
146: + password + "'");
147: VerifierInfo info = new VerifierInfo();
148: info.username = username;
149: /*
150: long r = Util.nextLong();
151: String rs = Long.toHexString(r);
152: */
153: String rs = "123456";
154: info.salt = rs.getBytes();
155: try {
156: char[] pass = password.toCharArray();
157: info.verifier = Util.calculateVerifier(username, pass,
158: info.salt, N, g);
159: info.g = g.toByteArray();
160: info.N = N.toByteArray();
161: if (log.isTraceEnabled()) {
162: log.trace("N: " + Util.tob64(info.N));
163: log.trace("g: " + Util.tob64(info.g));
164: log.trace("s: " + Util.tob64(info.salt));
165: byte[] xb = Util.calculatePasswordHash(username, pass,
166: info.salt);
167: log.trace("x: " + Util.tob64(xb));
168: log.trace("v: " + Util.tob64(info.verifier));
169: byte[] hn = Util.newDigest().digest(info.N);
170: log.trace("H(N): " + Util.tob64(hn));
171: byte[] hg = Util.newDigest().digest(info.g);
172: log.trace("H(g): " + Util.tob64(hg));
173: }
174: } catch (Throwable t) {
175: log.error("Failed to calculate verifier", t);
176: return;
177: }
178:
179: setUserVerifier(username, info);
180: }
181:
182: public void delUser(String username) {
183: infoMap.remove(username);
184: }
185:
186: public static void main(String[] args) throws IOException {
187: File storeFile = new File("SerialObjectStore.ser");
188: SerialObjectStore store = new SerialObjectStore();
189:
190: for (int a = 0; a < args.length; a++) {
191: if (args[a].startsWith("-a")) {
192: store.addUser(args[a + 1], args[a + 2]);
193: } else if (args[a].startsWith("-d")) {
194: store.delUser(args[a + 1]);
195: }
196: }
197: store.save(storeFile);
198: }
199: }
|