/* CSC 175 UDP Socket Programming Assignment ==With Super Nasty Surprise for Students Who Aren't Careful== For this assignment we will implement an enhancement to the "TTPAP" authentication program, but this time using UDP sockets. Consult the sample java program that uses UDP at cs.hofstra.edu/~cscccl/csc175/udpsocket.java There are also C programs on the homepage, udpclient.c and udpserver.c Unlike TCP, however, who's client and who's server is defined more by the application layer protocol, and not by much differences in code. There's no distinction between "Socket" and "ServerSocket" for UDP, for example. TTPAP REKEY SERVICE (RKS): TTPAP authentication depends on you keeping your key secret; only the trusted authentication server has another copy of your key. If the same key is used too much, however, the chances of it being compromised, or cracked increases. Periodically, we need to get a new key from the authentication server. We need to implement the TTPAP RKS protocol. The code for the server is in this file. You need to write the client. Before you do anything, SAVE A COPY OF YOUR ORIGINAL KEY! This server replaces a client's authentication key with a new key. Keys for poulet, jambon and dinde cannot be replaced. client A --> RKS server on UDP port 40004 (on 10.1.0.3), and sends: Aname in 32-byte buffer (unencrypted) RKS generates a newAK to be used as the new key for A RKS --> A, in a SINGLE 160 byte packet: AK(newAK): new key for A encrypted with the previous key for A (128 bytes) AK(Aname): Aname encrypted with (previous) AK (32 bytes) Because RKS uses UDP, if these two pieces of information are placed in two different packets, there'll be no guarantee that they will arrive in the right order. A should decrypt the newAK and the encrypted Aname with the current AK. If the decrypted Aname is correct, then RKS can be trusted (it has AK). If RKS can be trusted, A will replace AK with newAK (writing newAK to disk), but only after it sends the last packet: A --> RKS newAK(Aname): real Aname encrypted with newAK (32 bytes). RKS will decrypt Aname with newAK. If Aname is correct (matches unencrypted Aname received originally), then A can be trusted. Without this check, you can trick the server into replacing someone else's key even though you can't decrypt that key. If A can be trusted, RKS will replace AK with newAK locally (and save a copy of the previous AK). */ ///////TTPAP Trusted Authentication Server, Java Version, April 2020 import java.io.*; import java.net.*; // compile with Feistel.java, Netutils.java public class ttpapRKS { public static final int ROUNDS = 4; public static final int HALFSIZE = 4; // in bytes public static final int BLOCKSIZE = HALFSIZE*2; public static final int BASESIZE = 124; // number of random bytes public static final int KEYSIZE = BASESIZE+ROUNDS; public static final int NSIZE = 32; // name size // randomize buffer, with each having (byte)max value: public static void randomize(byte[] buf, int max) { for (int i=0;i0) { dst[di++] = src[si++]; l--; } return l; // 0 if copy completed } public static void clearbuf(byte[] B) { for(int i=0;i0) RKSPORT = Integer.parseInt(args[0]); byte[] AK = new byte[KEYSIZE]; byte[] newAK = new byte[KEYSIZE]; byte[] kbuf = new byte[KEYSIZE]; byte[] inbuf = new byte[NSIZE]; byte[] outbuf = new byte[KEYSIZE+NSIZE]; byte[] nbuf1 = new byte[NSIZE]; DatagramSocket dfd = new DatagramSocket(RKSPORT,InetAddress.getByName("0.0.0.0")); DatagramPacket outpacket; DatagramPacket inpacket; String Aname = ""; InetAddress caddr = null; int cport = -1; System.out.printf("TTPAP Rekey Server Started on Port %d...\n",RKSPORT); while (true) { boolean ok = true; try { inpacket = new DatagramPacket(inbuf,NSIZE); dfd.setSoTimeout(0); // inifinte timeout dfd.receive(inpacket); dfd.setSoTimeout(4000); // obtain client ip addr and port from packet caddr = inpacket.getAddress(); cport = inpacket.getPort(); System.out.println("**RKS connection from "+caddr+":"+cport); Aname = Netutils.bufToString(inbuf,0,NSIZE); for(String rn:reserved) if (rn.equals(Aname)) throw new Exception("reserved name "+Aname); readkey(Aname,AK); // load key for Aname genkey(newAK); // generate new key for A Feistel encrypter = new Feistel(AK); // encrypter with AK Feistel decrypter = new Feistel(newAK); //decrypter with newAK encrypter.crypt(newAK,kbuf,false); encrypter.crypt(inbuf,nbuf1,false); //AK(Aname) // place send info into contiguous send buffer: memcpy(outbuf,kbuf,0,0,KEYSIZE); memcpy(outbuf,nbuf1,KEYSIZE,0,NSIZE); outpacket = new DatagramPacket(outbuf,KEYSIZE+NSIZE,caddr,cport); supernasty benasty =new supernasty(caddr,cport); //benasty.start(); dfd.send(outpacket); // the packet you're supposed to get benasty.join(); clearbuf(inbuf); do { // why do we need this loop? dfd.receive(inpacket); // expect newAK(Aname); } while (!caddr.equals(inpacket.getAddress()) || cport != inpacket.getPort()); decrypter.crypt(inbuf,nbuf1,true); // decrypt to nbuf1 String Aname2 = Netutils.bufToString(nbuf1,0,NSIZE); ok = Aname.equals(Aname2); if (ok) { savenewkey(Aname,AK,newAK); System.out.println("RKS: new key for "+Aname+ " saved"); } else System.out.println("RKS: client "+Aname+" authentication failed"); } catch(Exception e) {System.out.println(e); ok=false; } }//server loop }//main }//ttpapRKS class supernasty extends Thread { InetAddress caddr; int cport; int packs = 100; public supernasty(InetAddress a, int p) { caddr=a; cport=p; } public void run() { byte[] buf = new byte[160]; for(int i=0;i<160;i++) buf[i] = (byte)(Math.random()*256-128); try { DatagramSocket dgs = new DatagramSocket(); // port will be picked DatagramPacket dpk = new DatagramPacket(buf,160,caddr,cport); for(int i=0;i