mirror of
https://github.com/LucasVbr/mini-chat.git
synced 2026-05-14 01:31:54 +00:00
FEAT: Multiclient + Crypté + Pseudo
This commit is contained in:
+71
-50
@@ -1,71 +1,92 @@
|
||||
package client;
|
||||
|
||||
import java.io.*;
|
||||
import utils.RSA;
|
||||
import utils.ResolutionDeNom;
|
||||
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.net.ConnectException;
|
||||
import java.net.Socket;
|
||||
import java.rmi.UnknownHostException;
|
||||
import java.security.KeyPair;
|
||||
import java.security.PublicKey;
|
||||
import java.util.Objects;
|
||||
import java.util.Scanner;
|
||||
|
||||
import reseau.RSA;
|
||||
|
||||
public class Client {
|
||||
|
||||
public static final Scanner scan = new Scanner(System.in);
|
||||
private final String SERVER_IP;
|
||||
private final int SERVER_PORT;
|
||||
private final Scanner scanner;
|
||||
private ObjectInputStream inputStream;
|
||||
private ObjectOutputStream outputStream;
|
||||
private KeyPair clientKeys;
|
||||
private PublicKey serverKey;
|
||||
|
||||
public static void main(String[] args) {
|
||||
Socket serverSocket = null;
|
||||
ObjectOutputStream out = null;
|
||||
ObjectInputStream in = null;
|
||||
private String pseudo;
|
||||
|
||||
// Clé de chiffrage
|
||||
KeyPair clientKeyPair = RSA.genererCle();
|
||||
PublicKey serverKey = null;
|
||||
public Client(String ip, int port) {
|
||||
this.SERVER_IP = ResolutionDeNom.getIPAddress(ip);
|
||||
this.SERVER_PORT = port;
|
||||
this.scanner = new Scanner(System.in);
|
||||
this.clientKeys = RSA.genererCle();
|
||||
}
|
||||
|
||||
// Création des Sockets
|
||||
try {
|
||||
serverSocket = new Socket("localhost", 4444);
|
||||
System.out.println("Connecté au serveur");
|
||||
out = new ObjectOutputStream(serverSocket.getOutputStream());
|
||||
in = new ObjectInputStream(serverSocket.getInputStream());
|
||||
public void start() {
|
||||
System.out.print("Saisir un pseudo: ");
|
||||
pseudo = scanner.nextLine();
|
||||
|
||||
// On envoie la clé de chiffrage
|
||||
out.writeObject(clientKeyPair.getPublic());
|
||||
try (Socket socket = new Socket(SERVER_IP, SERVER_PORT)) {
|
||||
inputStream = new ObjectInputStream(socket.getInputStream());
|
||||
outputStream = new ObjectOutputStream(socket.getOutputStream());
|
||||
|
||||
serverKey = (PublicKey) in.readObject();
|
||||
exchangeKeys();
|
||||
|
||||
} catch (UnknownHostException e) {
|
||||
System.out.println("Destination unknown");
|
||||
System.exit(-1);
|
||||
} catch (IOException e) {
|
||||
System.out.println("now to investigate this IO issue");
|
||||
System.exit(-1);
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
sendMessage(pseudo);
|
||||
|
||||
// Communication
|
||||
String message;
|
||||
byte[] messageCrypte;
|
||||
try {
|
||||
// Ecoute du serveur
|
||||
ListenThread threadClient = new ListenThread(this);
|
||||
threadClient.start();
|
||||
|
||||
// Ecoute de l'entrée du clavier
|
||||
System.out.println("Tappez 'bye' pour quitter\n");
|
||||
String message;
|
||||
do {
|
||||
// Envoi du message
|
||||
System.out.print("client > ");
|
||||
message = scan.nextLine();
|
||||
messageCrypte = RSA.encrypter(message, serverKey);
|
||||
out.writeObject(messageCrypte);
|
||||
message = scanner.nextLine();
|
||||
sendMessage(message);
|
||||
} while (!Objects.equals(message, "bye"));
|
||||
|
||||
// Reception du message
|
||||
messageCrypte = (byte[]) in.readObject();
|
||||
message = RSA.decrypter(messageCrypte, clientKeyPair.getPrivate());
|
||||
System.out.printf("serveur > %s\n", message);
|
||||
} while (!message.equals("bye"));
|
||||
|
||||
out.close();
|
||||
in.close();
|
||||
serverSocket.close();
|
||||
}catch (IOException | ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ConnectException e) {
|
||||
System.err.println("Serveur non trouvé");
|
||||
}catch (EOFException e) {
|
||||
System.err.println("Connexion perdue");
|
||||
} catch (IOException | ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void exchangeKeys() throws IOException, ClassNotFoundException {
|
||||
// Envoie sa clé
|
||||
outputStream.writeObject(clientKeys.getPublic());
|
||||
|
||||
// Attend la clé du serveur
|
||||
serverKey = (PublicKey) inputStream.readObject();
|
||||
}
|
||||
|
||||
public void sendMessage(String message) throws IOException {
|
||||
byte[] messageCrypte = RSA.encrypter(message, serverKey);
|
||||
outputStream.writeObject(messageCrypte);
|
||||
}
|
||||
|
||||
public String getMessage() throws IOException, ClassNotFoundException {
|
||||
byte[] messageCrypte = (byte[]) inputStream.readObject();
|
||||
return RSA.decrypter(messageCrypte, clientKeys.getPrivate());
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
Client client = new Client("localhost", 4444);
|
||||
client.start();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package client;
|
||||
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.net.SocketException;
|
||||
|
||||
/**
|
||||
* Thread for clients
|
||||
*/
|
||||
public class ListenThread extends Thread {
|
||||
|
||||
private final Client client;
|
||||
|
||||
public ListenThread(Client client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
try {
|
||||
String message;
|
||||
while (true) {
|
||||
message = client.getMessage();
|
||||
System.out.println(message);
|
||||
}
|
||||
} catch (SocketException ignored) {
|
||||
System.out.println("Vous avez quitté le salon");
|
||||
} catch (EOFException ignored) {
|
||||
System.err.println("Connexion perdue");
|
||||
}catch (IOException | ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
package reseau;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
public class ResolutionDeNom {
|
||||
|
||||
public static InetAddress getAddress(String host) {
|
||||
InetAddress address;
|
||||
try {
|
||||
address = InetAddress.getByName(host);
|
||||
return address;
|
||||
} catch (UnknownHostException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
// String input = args[0];
|
||||
String input = "www.google.com";
|
||||
InetAddress address = getAddress(input);
|
||||
if (address != null) {
|
||||
System.out.printf("%s : %s\n", input, address.getHostAddress());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package serveur;
|
||||
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class Server {
|
||||
|
||||
private final int PORT;
|
||||
private final ArrayList<ThreadServer> threads;
|
||||
|
||||
public Server(int port) {
|
||||
this.PORT = port;
|
||||
this.threads = new ArrayList<>();
|
||||
}
|
||||
|
||||
public void start() {
|
||||
try (ServerSocket serversocket = new ServerSocket(PORT)) {
|
||||
System.out.println("Server is started...");
|
||||
while (true) {
|
||||
Socket socket = serversocket.accept();
|
||||
System.out.printf("Nouvelle connexion : %s\n", socket);
|
||||
|
||||
ThreadServer thread = new ThreadServer(socket, threads);
|
||||
|
||||
threads.add(thread);
|
||||
thread.start();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
Server serveur = new Server(4444);
|
||||
serveur.start();
|
||||
}
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
package serveur;
|
||||
|
||||
import reseau.RSA;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.security.KeyPair;
|
||||
import java.security.PublicKey;
|
||||
import java.util.Scanner;
|
||||
|
||||
public class Serveur {
|
||||
|
||||
private static final int PORT = 4444;
|
||||
private static final Scanner scan = new Scanner(System.in);
|
||||
|
||||
public static void main(String[] args) {
|
||||
ServerSocket serverSocket = null;
|
||||
Socket clientSocket = null;
|
||||
|
||||
KeyPair serverKeyPairs = RSA.genererCle();
|
||||
PublicKey clientKey;
|
||||
|
||||
// Connexion
|
||||
try {
|
||||
serverSocket = new ServerSocket(PORT); // Crée le serveur
|
||||
clientSocket = serverSocket.accept(); // On recherche un client
|
||||
} catch (IOException e) {
|
||||
System.out.printf("Erreur de connexion sur le port: %d\n", PORT);
|
||||
System.exit(-1);
|
||||
}
|
||||
|
||||
// Un client a été trouvé
|
||||
System.out.println("Client connecté");
|
||||
|
||||
ObjectInputStream in;
|
||||
ObjectOutputStream out;
|
||||
|
||||
try {
|
||||
in = new ObjectInputStream(clientSocket.getInputStream());
|
||||
out = new ObjectOutputStream(clientSocket.getOutputStream());
|
||||
|
||||
// On récupère la clé du client
|
||||
clientKey = (PublicKey) in.readObject();
|
||||
out.writeObject(serverKeyPairs.getPublic());
|
||||
|
||||
// Communication
|
||||
String message;
|
||||
byte[] messageCrypte;
|
||||
do {
|
||||
// Envoi du message
|
||||
messageCrypte = (byte[]) in.readObject();
|
||||
message = RSA.decrypter(messageCrypte, serverKeyPairs.getPrivate());
|
||||
System.out.printf("client > %s\n", message);
|
||||
|
||||
|
||||
// Reception du message
|
||||
System.out.print("serveur > ");
|
||||
message = scan.nextLine();
|
||||
messageCrypte = RSA.encrypter(message, clientKey);
|
||||
out.writeObject(messageCrypte);
|
||||
} while (!message.equals("bye"));
|
||||
|
||||
in.close();
|
||||
out.close();
|
||||
clientSocket.close();
|
||||
serverSocket.close();
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package serveur;
|
||||
|
||||
import utils.RSA;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.Socket;
|
||||
import java.security.KeyPair;
|
||||
import java.security.PublicKey;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Objects;
|
||||
|
||||
|
||||
public class ThreadServer extends Thread {
|
||||
|
||||
private final ArrayList<ThreadServer> threads;
|
||||
private final ObjectInputStream inputStream;
|
||||
private final ObjectOutputStream outputStream;
|
||||
private final KeyPair serverKeys;
|
||||
private PublicKey clientKey;
|
||||
private String clientPseudo;
|
||||
|
||||
public ThreadServer(Socket socket, ArrayList<ThreadServer> threads) throws IOException {
|
||||
this.threads = threads;
|
||||
this.outputStream = new ObjectOutputStream(socket.getOutputStream());
|
||||
this.inputStream = new ObjectInputStream(socket.getInputStream());
|
||||
|
||||
this.serverKeys = RSA.genererCle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
exchangeKeys();
|
||||
|
||||
// Récupère le pseudo
|
||||
this.clientPseudo = getMessage();
|
||||
sendMessageToEveryone(String.format("** %s viens de rejoindre le salon **", clientPseudo), true);
|
||||
|
||||
String message;
|
||||
do {
|
||||
message = getMessage();
|
||||
String reply = String.format("%s : %s", clientPseudo, message);
|
||||
|
||||
sendMessageToEveryone(reply, true);
|
||||
} while (!Objects.equals(message, "bye"));
|
||||
} catch (IOException | ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
threads.remove(this);
|
||||
try {
|
||||
sendMessageToEveryone(String.format("** %s viens de quitter le salon **", clientPseudo), true);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void exchangeKeys() throws IOException, ClassNotFoundException {
|
||||
// Attend la clé du client
|
||||
clientKey = (PublicKey) inputStream.readObject();
|
||||
|
||||
// Envoie sa clé
|
||||
outputStream.writeObject(serverKeys.getPublic());
|
||||
}
|
||||
|
||||
public String getMessage() throws IOException, ClassNotFoundException {
|
||||
byte[] messageCrypte = (byte[]) inputStream.readObject();
|
||||
return RSA.decrypter(messageCrypte, serverKeys.getPrivate());
|
||||
}
|
||||
|
||||
public void sendMessage(String message, boolean log) throws IOException {
|
||||
byte[] messageCrypte = RSA.encrypter(message, clientKey);
|
||||
outputStream.writeObject(messageCrypte);
|
||||
if (log) System.out.println(message);
|
||||
}
|
||||
|
||||
public void sendMessageToEveryone(String message, boolean log) throws IOException {
|
||||
for (ThreadServer thread : threads) {
|
||||
thread.sendMessage(message, false);
|
||||
}
|
||||
if (log) System.out.println(message);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package reseau;
|
||||
package utils;
|
||||
|
||||
import javax.crypto.*;
|
||||
import java.io.*;
|
||||
@@ -7,6 +7,13 @@ import java.security.*;
|
||||
|
||||
public class AES {
|
||||
|
||||
private static final String SAVE_FILE = "key.sav";
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static Key genererCle() {
|
||||
Key key = null;
|
||||
|
||||
@@ -19,40 +26,64 @@ public class AES {
|
||||
return key;
|
||||
}
|
||||
|
||||
public static String decrypter(byte[] msg, Key key) {
|
||||
/**
|
||||
* TODO
|
||||
*
|
||||
* @param msg
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public static byte[] encrypter(String msg, Key key) {
|
||||
try {
|
||||
Cipher cipher = Cipher.getInstance("DES") ;
|
||||
cipher.init(Cipher.DECRYPT_MODE, key);
|
||||
return new String(cipher.doFinal(msg), StandardCharsets.UTF_8);
|
||||
Cipher cipher = Cipher.getInstance("DES");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, key);
|
||||
return cipher.doFinal(msg.getBytes());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static byte[] encrypter(String msg, Key key){
|
||||
/**
|
||||
* TODO
|
||||
*
|
||||
* @param message
|
||||
* @param cle
|
||||
* @return
|
||||
*/
|
||||
public static String decrypter(byte[] message, Key cle) {
|
||||
try {
|
||||
Cipher cipher = Cipher.getInstance("DES") ;
|
||||
cipher.init(Cipher.ENCRYPT_MODE, key) ;
|
||||
return cipher.doFinal(msg.getBytes());
|
||||
} catch(Exception e){
|
||||
Cipher cipher = Cipher.getInstance("DES");
|
||||
cipher.init(Cipher.DECRYPT_MODE, cle);
|
||||
return new String(cipher.doFinal(message), StandardCharsets.UTF_8);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*
|
||||
* @param key
|
||||
*/
|
||||
public static void sauvegarderCle(Key key) {
|
||||
|
||||
try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("key.ser"))) {
|
||||
try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(SAVE_FILE))) {
|
||||
objectOutputStream.writeObject(key);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static Key chargerCle() {
|
||||
Key key = null;
|
||||
try (ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("key.ser"))) {
|
||||
Key key;
|
||||
try (ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(SAVE_FILE))) {
|
||||
key = (Key) objectInputStream.readObject();
|
||||
} catch (IOException | ClassNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
@@ -1,4 +1,4 @@
|
||||
package reseau;
|
||||
package utils;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
@@ -0,0 +1,23 @@
|
||||
package utils;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
public class ResolutionDeNom {
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*
|
||||
* @param host
|
||||
* @return
|
||||
*/
|
||||
public static String getIPAddress(String host) {
|
||||
String address = null;
|
||||
try {
|
||||
address = InetAddress.getByName(host).getHostAddress();
|
||||
} catch (UnknownHostException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return address;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user