www.pudn.com > encryption.rar > AuthServer.java
/*
Christoforos Pirillos @ Villanova University - May 1999
based on code from the book "Java Network Programming" by Hughes
*/
package encryption;
import java.io.*;
import java.net.*;
import java.util.*;
/**Implements an authenticating secure server*/
public class AuthServer {
Socket s;
int port;
protected X9_17KeyGen keys;
protected Hashtable passwords, ivs;
// used to create a dummy AuthServer, in order to add users in the
//database
public AuthServer () {
passwords=new Hashtable();
ivs=new Hashtable();
}
/**Accepts a random seedText which uses to generate the keys, and a port
number to start listening for incoming connections*/
public AuthServer (String seedText, int port) throws IOException {
this.port=port;
keys=new X9_17KeyGen (Password.keyFromPassword(seedText),
Password.nextKeyFromPassword (seedText));
passwords=new Hashtable();
ivs=new Hashtable();
//open the passfile and read the existing entries into the Hashtables
try {
BufferedReader passfile= new BufferedReader
( new FileReader("passfile") );
String entry;
try {
while ( (entry=passfile.readLine())!=null ) {
StringTokenizer tokens = new StringTokenizer(entry);
String username = tokens.nextToken();
String password = tokens.nextToken();
byte[] iv = new byte[8];
System.out.println(username);
Crypt.longToBytes(Long.parseLong(
tokens.nextToken()),
iv, 0);
passwords.put(username,new Long (password) );
ivs.put (username, iv);
}
}catch (IOException e) {}
passfile.close();
} catch (FileNotFoundException e) {
System.out.println(e);
System.exit(0);
}
}
/**Accepts a username and password and puts them into the database*/
public void setPassword (String user, String password) throws IOException
{
passwords.put (user,new Long
(Password.keyFromPassword(password)));
byte[] iv=new byte[8];
Crypt.longToBytes (Password.nextKeyFromPassword(password),iv,0);
ivs.put(user,iv);
// open the password file and store the pairs
FileWriter passfile = new FileWriter("passfile",true);
Enumeration users = passwords.keys();
while (users.hasMoreElements()) {
Object key = users.nextElement();
String entry =
key.toString()+" "+
passwords.get(key).toString()+" "+
Long.toString( Crypt.bytesToLong
((byte[])ivs.get(key),0)) +
"\n";
System.out.println(entry);
passfile.write(entry,0,entry.length());
}
passfile.close();
}
/**The authentication of the client takes place in this method. It accepts
two streams and the Socket the client is connected on. If authentication
fails, it will throw an exception.*/
public void authenticate (InputStream i, OutputStream o, Socket s) throws
IOException {
String user = new DataInputStream(i).readUTF();
long sessionKey=DES.paritySet (keys.nextKey());
new DataOutputStream(o).writeLong(encodeKey(user,sessionKey));
o.flush();
Cipher sessionDES = new CBCCipher (new DES(sessionKey),
(byte[])ivs.get(user));
byte[] temp = new byte[8];
new DataInputStream(i).readFully(temp);
long challenge = Crypt.bytesToLong(sessionDES.decipher(temp),0);
Crypt.longToBytes (challenge+1, temp, 0);
o.write (sessionDES.encipher(temp));
try {
new DataInputStream(i).readFully(temp);
long
complete=Crypt.bytesToLong(sessionDES.decipher(temp),0);
if (complete != challenge + 2)
throw new AuthException("Incorrect Password.");
}catch (EOFException ex) {
throw new AuthException ("Challenge/response failed.");
}
InputStream sessionI=new CipherInputStream(i,sessionDES);
OutputStream sessionO=new CipherOutputStream (o,sessionDES);
accept (user, sessionI, sessionO, s);
}
/**Creates a new proxy server that will redirect the secure streams to the
telnet port (port 23)*/
protected void accept (String name, InputStream i, OutputStream o, Socket s)
{
new proxy(port, "localhost",23,name,i,o,s);
}
/**Encrypts a session key with the user's password*/
protected long encodeKey (String user, long key) throws AuthException {
if (!passwords.containsKey(user))
throw new AuthException("User not registered.");
Long password = (Long)passwords.get(user);
DES des=new DES (password.longValue());
return des.encrypt(key);
}
/** Starts the Server at the port given on the command line and also uses
the second command line argument as seed text*/
public static void main (String args[]) throws IOException {
if (args.length < 2)
throw new RuntimeException
("Syntax: AuthServer {seed text}\n"+
" -user ");
// if a user-password is given, put it in the passfile and exit
if (args[0].equals("-user")) {
AuthServer dummyauth = new AuthServer();
dummyauth.setPassword(args[1],args[2]);
System.exit(0);
}
int port = Integer.parseInt(args[0]);
ServerSocket server = new ServerSocket(port);
StringBuffer seed=new StringBuffer();
for (int i=1;i