Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

JAVA modify program I have a multi client / server chat program that uses Diffie

ID: 3902028 • Letter: J

Question

JAVA modify program

I have a multi client / server chat program that uses Diffie Hellman key exchange to encrypt messages. Entire Program provided, can you please make changes to have it run on the command line where and port number, P and Q, are entered in the servers command line. thank you. JAVA

DiffieServer.Java

}

DiffieClient.java

}

Connection.java

package chat.server; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; import chat.net.Connection; public class DiffieServer { private ServerSocket ssock; private ArrayList<Connection> clients; public static void main(String args[]) { DiffieServer server = new DiffieServer(5050); server.start(); } public DiffieServer(int port) { try { ssock = new ServerSocket(port); } catch (IOException e) { e.printStackTrace(); System.exit(1); } } public void start() { System.out.println("Server started..."); clients = new ArrayList<Connection>(); BroadcastThread bct = new BroadcastThread(); bct.start(); try { while (true) { Socket csock = ssock.accept(); Connection newClient = new Connection(csock); newClient.sendKey(); clients.add(newClient); System.out.println("** New Client: " + csock.toString()); } } catch (IOException e) { e.printStackTrace(); System.exit(1); } } private class BroadcastThread extends Thread { public void run() { while (true) { try { for (int i = 0; i < clients.size(); i++) { if (clients.get(i).hasMessage()) { String message = clients.get(i).getMessage(); broadcastMessage(message); System.out.println(message); } } Thread.sleep(500); } catch (Exception e) { e.printStackTrace(); System.exit(1); } } } private void broadcastMessage(String message) { for (int i = 0; i < clients.size(); i++) { clients.get(i).sendMessage(message); } } }

}

Explanation / Answer

DiffieClient.java

import java.io.*;

import java.net.*;

import java.security.*;

import java.security.spec.*;

import javax.crypto.*;

import javax.crypto.spec.*;

import java.math.BigInteger;

import java.util.Random;

import sun.misc.BASE64Decoder;

import sun.misc.BASE64Encoder;

public class Client

{

private Socket sock; //Socket to communicate with.

private DataOutputStream out; //outstream for sock

private DataInputStream in; //instream for sock

private byte[] aesKey; // shared AES key for all encryption

private boolean debug; //print debug messages?

/**

* Main method, starts the client.

* @param args args[0] needs to be a hostname, args[1] a port number.

*/

public static void main (String [] args)

{

boolean setDebug = false;

if (args.length < 2)

{

System.out.println ("Usage: java Client hostname port# <debug>");

System.out.println ("hostname is a string identifying your server");

System.out.println ("port is a positive integer identifying the port to connect to the server");

return;

}

if (args.length == 3)

{

if(args[2].compareTo("debug") == 0)

{

setDebug = true;

}

}

try {

Client cl = new Client (args[0], Integer.parseInt(args[1]), setDebug);

}

catch (NumberFormatException e) {

System.out.println ("Usage: java Client hostname port#");

System.out.println ("Second argument was not a port number");

return;

}

}

/**

* Constructor, in this case does everything.

* @param ipaddress The hostname to connect to.

* @param port The port to connect to.

*/

public Client (String ipaddress, int port, boolean setDebug)

{

debug = setDebug;

/* Allows us to get input from the keyboard. */

BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));

/* Try to connect to the specified host on the specified port. */

try {

sock = new Socket (InetAddress.getByName(ipaddress), port);

}

catch (UnknownHostException e) {

System.out.println ("Usage: java Client hostname port#");

System.out.println ("First argument is not a valid hostname");

return;

}

catch (IOException e) {

System.out.println ("Could not connect to " + ipaddress + ".");

return;

}

/* Status info */

System.out.println ("Connected to " + sock.getInetAddress().getHostAddress() + " on port " + port);

try {

in = new DataInputStream(sock.getInputStream());

out = new DataOutputStream(sock.getOutputStream());

}

catch (UnknownHostException e) {

System.out.println ("Unknown host error.");

return;

}

catch (IOException e) {

System.out.println ("Could not create output stream.");

return;

}

//get shared AES key for encrypting file

aesKey = key_agreement();

debug(new String(aesKey));

send_file();

System.out.println ("Client exiting.");

try {

out.close();

in.close();

sock.close();

stdIn.close();

} catch (IOException e) {

return;

}

}

//Diffie-Hellman key agreement protocol

//Based on implementation in JCE docs

public byte[] key_agreement()

{

debug("Starting key agreement");

try {

/*

*** Generate the parameters for diffie-hellman

*/

//Get the 1024 bit prime number p

byte[] encodedp = receive();

//Decode encodedp into a BigInteger p

BASE64Decoder mybase64decoder = new BASE64Decoder( );

byte[] pbytes = mybase64decoder.decodeBuffer( new String(encodedp) );

BigInteger p= new BigInteger(pbytes);

debug("Client Received p:"+p);

//Get the primitive element

byte[] encodedg = receive();

//Decode encodedg into a BigInteger g

byte[] gbytes = mybase64decoder.decodeBuffer( new String(encodedg) );

BigInteger g= new BigInteger(gbytes);

debug("Client Received g:"+g);

//Generate the private data (random a)

boolean gooda=false;

BigInteger (long) 1);

BigInteger pminusone= p.subtract( one);

SecureRandom myrand = SecureRandom.getInstance("SHA1PRNG");

BigInteger a=null;

while( !gooda ){

a = new BigInteger(1025,myrand);

if (a.compareTo(pminusone) < 0){

gooda= true;

}

}

//Compute the public key (g^a) (using your own fast exponentiation)

BigInteger ya= Utilities.fastmodexp( g ,a,p);

//Encode the public key in base 64

BASE64Encoder mybase64encoder = new BASE64Encoder();

String ya64string = mybase64encoder.encodeBuffer( ya.toByteArray() );

debug("Receiving servers public key, yb");

//get servers public key

byte[] ybstringbytes = receive();

//send the encoded clients public key

debug("Sending public key, ya, to Server");

send( ya64string);

//Decode the server public key

// g^b = decoded(ybstringbytes)

byte[] ybbytes = mybase64decoder.decodeBuffer( new String(ybstringbytes) );

BigInteger yb= new BigInteger(ybbytes);

//Get shared key

debug("Derive the DH key in Client");

// key = (g^b)^a

BigInteger key= Utilities.fastmodexp(yb,a,p);

//Apply a hash function to the key

byte[] secretKey = Utilities.keyhash(key.toByteArray() );

debug("Finished key agreement");

return secretKey;

} catch (Exception e) {

e.printStackTrace();

return null;

}

}

public void send_file()

{

BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));

String infilename;

String outfilename;

FileInputStream infile;

byte[] message;

byte[] messagehash;

byte[] ciphertext;

try {

debug("Starting File Transfer");

System.out.println("Please enter the source filename:");

infilename = stdIn.readLine();

infile = new FileInputStream(infilename);

System.out.println("Please enter the destination filename:");

outfilename = stdIn.readLine();

//Send the output file name

send(Utilities.encrypt(outfilename.getBytes(), aesKey));

//Send the filesize

send(Utilities.encrypt(String.valueOf(infile.available()).getBytes(), aesKey));

//Load file into byte array

message = new byte[infile.available()];

infile.read(message);

//append the hash/mac for data integrity

messagehash = Utilities.append_hash(message, aesKey);

//Encrypt the message/mac

ciphertext = Utilities.encrypt(messagehash, aesKey);

debug("Sending ciphertext");

//Send the encrypted file

send(ciphertext);

debug("ciphertext sent");

debug("get verification status");

String verified = new String(receive());

if(verified.compareTo("Passed") == 0)

{

System.out.println("File verification passed.");

}

else

{

System.out.println("File verification failed.");

}

infile.close();

} catch (Exception e) {

System.out.println ("Could not read source file");

return;

}

}

public int send(String message)

{

return Utilities.send(message.getBytes(), out);

}

public int send(byte[] message)

{

return Utilities.send(message, out);

}

public byte[] receive() throws IOException

{

return Utilities.receive(in);

}

private void debug(String s)

{

if(debug) System.out.println("Debug: " + s);

}

}

Diffieserver.java

import java.io.IOException;

import java.net.*;

import java.util.Vector;

public class Server

{

private ServerSocket serversock;

private Vector <ServerThread> serverthreads; //holds the active threads

private boolean shutdown; //allows clients to shutdown the server

private int clientcounter; //id numbers for the clients

boolean debug = false; //print debug messages?

/**

* Main method

* @param args First argument should be the port to listen on.

*/

public static void main (String [] args)

{

boolean setDebug = false;

if (args.length < 1)

{

System.out.println ("Usage: java Server port#");

return;

}

if (args.length == 2)

{

if(args[1].compareTo("debug") == 0)

{

setDebug = true;

}

}

try {

Server serv = new Server (Integer.parseInt(args[0]), setDebug);

}

catch (ArrayIndexOutOfBoundsException e) {

System.out.println ("Usage: java Server port#");

System.out.println ("Second argument is not a port number.");

return;

}

catch (NumberFormatException e) {

System.out.println ("Usage: java Server port#");

System.out.println ("Second argument is not a port number.");

return;

}

}

/**

* Constructor, makes a new server listening on specified port.

* @param port The port to listen on.

*/

public Server (int port, boolean setDebug)

{

debug = setDebug;

clientcounter = 0;

shutdown = false;

try {

serversock = new ServerSocket (port);

}

catch (IOException e) {

System.out.println ("Could not create server socket.");

return;

}

/* Server socket open, make a vector to store active threads. */

serverthreads = new Vector <ServerThread> (0,1);

/* listen on the socket for connections. */

listen ();

}

/**

* Allows threads to check and see if the server is shutting down.

* @return True if the server has been told to shutdown.

*/

public boolean getFlag ()

{

return shutdown;

}

/**

* Called by a thread who's client has asked to exit. Gets rid of the thread.

* @param st The ServerThread to remove from the vector of active connections.

*/

public void kill (ServerThread st)

{

System.out.println ("Killing Client " + st.getID() + ".");

/* Find the thread in the vector and remove it. */

for (int i = 0; i < serverthreads.size(); i++)

{

if (serverthreads.elementAt(i) == st)

serverthreads.remove(i);

}

}

/**

* Called by a thread who's client has instructed the server to shutdown.

*/

public void killall ()

{

shutdown = true;

System.out.println ("Shutting Down Server.");

/* For each active thread, close it's socket. This will cause the thread

* to stop blocking because of the IO operation, and check the shutdown flag.

* The thread will then exit itself when it sees shutdown is true. Then exits. */

for (int i = serverthreads.size() - 1; i >= 0; i--)

{

try {

System.out.println ("Killing Client " + serverthreads.elementAt(i).getID() + ".");

serverthreads.elementAt(i).getSocket().close();

}

catch (IOException e)

{System.out.println ("Could not close socket.");}

serverthreads.remove(i);

}

try {

serversock.close();

}

catch (IOException e) {

System.out.println ("Could not close server socket.");

}

}

/**

* Waits for incoming connections and spins off threads to deal with them.

*/

private void listen ()

{

Socket client = new Socket ();

ServerThread st;

/* Should only do this when it hasn't been told to shutdown. */

while (!shutdown)

{

/* Try to accept an incoming connection. */

try {

client = serversock.accept ();

/* Spew some info about the client */

System.out.println ("Client on machine " + client.getInetAddress().getHostAddress() + " has connected on port " + client.getLocalPort() + ".");

/* Create a new thread to deal with the client, add it to the vector of open connections.

* Finally, start the thread's execution. Start method makes the threads go by calling their

* run() methods. */

st = new ServerThread (client, this, clientcounter++);

serverthreads.add (st);

st.start ();

}

catch (IOException e) {

/* Server Socket is closed, probably because a client told the server to shutdown */

}

}

}

}