diff --git a/client/src/main/java/org/orinprojects/Client.java b/client/src/main/java/org/orinprojects/client/Client.java
similarity index 96%
rename from client/src/main/java/org/orinprojects/Client.java
rename to client/src/main/java/org/orinprojects/client/Client.java
index 21101bd..ca2eeaa 100644
--- a/client/src/main/java/org/orinprojects/Client.java
+++ b/client/src/main/java/org/orinprojects/client/Client.java
@@ -1,4 +1,4 @@
-package org.orinprojects;
+package org.orinprojects.client;
import org.orinprojects.encryption.EncryptionUtil;
import org.orinprojects.exceptions.ArgumentsException;
@@ -7,7 +7,9 @@ import javax.crypto.SecretKey;
import java.net.Socket;
import java.security.KeyPair;
import java.security.PublicKey;
-import java.util.*;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Scanner;
public class Client {
diff --git a/client/src/main/java/org/orinprojects/ClientThread.java b/client/src/main/java/org/orinprojects/client/ClientThread.java
similarity index 94%
rename from client/src/main/java/org/orinprojects/ClientThread.java
rename to client/src/main/java/org/orinprojects/client/ClientThread.java
index 1080e78..2b4f14e 100644
--- a/client/src/main/java/org/orinprojects/ClientThread.java
+++ b/client/src/main/java/org/orinprojects/client/ClientThread.java
@@ -1,15 +1,17 @@
-package org.orinprojects;
+package org.orinprojects.client;
import org.orinprojects.encryption.EncryptionUtil;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
-import java.io.*;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
import java.net.Socket;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
-import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
public class ClientThread implements Runnable {
diff --git a/desktop-client/pom.xml b/desktop-client/pom.xml
new file mode 100644
index 0000000..832dab4
--- /dev/null
+++ b/desktop-client/pom.xml
@@ -0,0 +1,62 @@
+
+
+ 4.0.0
+
+ org.orinprojects
+ SecuredChat
+ 1.0-SNAPSHOT
+
+
+ desktop-client
+
+
+ 20
+ 20
+ UTF-8
+
+
+
+
+ org.openjfx
+ javafx-controls
+ 19.0.2.1
+
+
+ org.openjfx
+ javafx-fxml
+ 19.0.2.1
+
+
+ org.orinprojects
+ server
+ 1.0-SNAPSHOT
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.8.1
+
+ 19
+ 19
+
+
+
+ org.openjfx
+ javafx-maven-plugin
+ 0.0.8
+
+ hellofx
+ securedChat
+ org.orinprojects.desktop.Main
+
+
+
+
+
+
\ No newline at end of file
diff --git a/desktop-client/src/main/java/module-info.java b/desktop-client/src/main/java/module-info.java
new file mode 100644
index 0000000..dbeaaff
--- /dev/null
+++ b/desktop-client/src/main/java/module-info.java
@@ -0,0 +1,9 @@
+module org.orinprojects.desktop {
+ requires javafx.controls;
+ requires javafx.fxml;
+ requires javafx.base;
+ requires org.orinprojects.server;
+
+ opens org.orinprojects.desktop to javafx.fxml;
+ exports org.orinprojects.desktop;
+}
\ No newline at end of file
diff --git a/desktop-client/src/main/java/org/orinprojects/desktop/ChatController.java b/desktop-client/src/main/java/org/orinprojects/desktop/ChatController.java
new file mode 100644
index 0000000..a375181
--- /dev/null
+++ b/desktop-client/src/main/java/org/orinprojects/desktop/ChatController.java
@@ -0,0 +1,89 @@
+package org.orinprojects.desktop;
+
+import javafx.event.ActionEvent;
+import javafx.geometry.Insets;
+import javafx.scene.control.Button;
+import javafx.scene.control.Label;
+import javafx.scene.control.TextField;
+import javafx.scene.layout.VBox;
+import javafx.scene.text.Font;
+import javafx.scene.text.Text;
+import org.orinprojects.encryption.EncryptionUtil;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import java.io.IOException;
+import java.net.Socket;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+
+import static org.orinprojects.desktop.Main.aesKey;
+import static org.orinprojects.desktop.Main.keys;
+
+public class ChatController {
+
+
+ public TextField messageTextInput;
+ public Button sendMsgBtn;
+ public Text welcomeMessage;
+ public Button connectBtn;
+ public Button disconnectBtn;
+ public TextField serverIpInput;
+ public TextField serverPortInput;
+ public TextField usernameInp;
+ public VBox messagesBox;
+
+ private Socket socket;
+
+ private ClientThread clientThread;
+
+ public void connect(ActionEvent actionEvent) throws IOException {
+ if (!serverIpInput.getText().equals("") && !serverPortInput.getText().equals("")) {
+ socket = new Socket(serverIpInput.getText(), Integer.parseInt(serverPortInput.getText()));
+
+ connectBtn.setDisable(true);
+ disconnectBtn.setDisable(false);
+ sendMsgBtn.setDisable(false);
+
+ clientThread = new ClientThread(socket, welcomeMessage, messagesBox);
+
+ Thread thr = new Thread(clientThread);
+ thr.start();
+
+ clientThread.out.println("WLC" + usernameInp.getText());
+ clientThread.out.flush();
+
+ clientThread.out.println("RSA" + EncryptionUtil.publicKeyToString(keys.getPublic()));
+ clientThread.out.flush();
+ }
+ }
+
+ public void disconnect(ActionEvent actionEvent) throws IOException {
+ clientThread.out.close();
+ clientThread.in.close();
+ socket.close();
+
+ connectBtn.setDisable(false);
+ disconnectBtn.setDisable(true);
+ sendMsgBtn.setDisable(true);
+ }
+
+ public void sendMessage(ActionEvent actionEvent) throws IllegalBlockSizeException, NoSuchPaddingException, BadPaddingException, NoSuchAlgorithmException, InvalidKeyException {
+ if (!clientThread.aesReceived && !clientThread.rsaReceived)
+ System.out.println("Wait for complete initialisation!");
+
+ if (clientThread.rsaReceived && clientThread.aesReceived) {
+ String encryptedText = EncryptionUtil.encryptWithAES(messageTextInput.getText(), aesKey);
+ clientThread.out.println("TXT" + encryptedText);
+ clientThread.out.flush();
+ }
+
+ Label text = new Label(messageTextInput.getText());
+ text.setFont(new Font(14));
+ text.setPadding(new Insets(0, 0, 5, 5));
+ messagesBox.getChildren().add(text);
+
+ messageTextInput.setText("");
+ }
+}
diff --git a/desktop-client/src/main/java/org/orinprojects/desktop/ClientThread.java b/desktop-client/src/main/java/org/orinprojects/desktop/ClientThread.java
new file mode 100644
index 0000000..e6c6b67
--- /dev/null
+++ b/desktop-client/src/main/java/org/orinprojects/desktop/ClientThread.java
@@ -0,0 +1,101 @@
+package org.orinprojects.desktop;
+
+import javafx.application.Platform;
+import javafx.geometry.Insets;
+import javafx.scene.control.Label;
+import javafx.scene.layout.VBox;
+import javafx.scene.text.Font;
+import javafx.scene.text.Text;
+import org.orinprojects.encryption.EncryptionUtil;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.net.Socket;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.spec.InvalidKeySpecException;
+
+public class ClientThread implements Runnable {
+
+ private final Socket clientSocket;
+
+ final BufferedReader in;
+
+ final PrintWriter out;
+
+ public boolean rsaReceived = false;
+
+ public boolean aesReceived = false;
+
+ public Text messageExample;
+
+ public VBox messagesBox;
+
+ public ClientThread(Socket socket, Text messageExample, VBox messagesBox) throws IOException {
+ this.clientSocket = socket;
+ this.messageExample = messageExample;
+ this.messagesBox = messagesBox;
+ this.in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
+ this.out = new PrintWriter(clientSocket.getOutputStream());
+ }
+
+ @Override
+ public void run() {
+ while (clientSocket.isConnected()) {
+ try {
+ String receivedMessage = in.readLine();
+ String prefix = receivedMessage.substring(0, 3);
+ String restMessage = receivedMessage.substring(3);
+
+ if (prefix.equals("RSA") && !rsaReceived) {
+ Main.serverPublicRSA = EncryptionUtil.stringToPublicKey(restMessage);
+ rsaReceived = true;
+ continue;
+ }
+
+ if (prefix.equals("AES") && !aesReceived) {
+ String decryptedAES = EncryptionUtil.decryptWithRSA(restMessage, Main.keys.getPrivate());
+ Main.aesKey = EncryptionUtil.aesKeyFromString(decryptedAES);
+ aesReceived = true;
+ continue;
+ }
+
+ if (prefix.equals("TXT") && aesReceived && rsaReceived) {
+ String decryptedMessage = EncryptionUtil.decryptWithAES(restMessage, Main.aesKey);
+
+ Label text = new Label(decryptedMessage);
+ text.setFont(new Font(14));
+ text.setPadding(new Insets(0, 0, 5, 5));
+
+ Platform.runLater(() -> messagesBox.getChildren().add(text));
+ }
+ } catch (NoSuchPaddingException | IllegalBlockSizeException | IOException | NoSuchAlgorithmException |
+ InvalidKeySpecException | BadPaddingException |InvalidKeyException e) {
+ System.err.println("Disconnected from server!");
+ System.exit(-1);
+ closeAllConnections(clientSocket, in, out);
+ }
+ }
+ }
+
+ private void closeAllConnections(Socket socket, BufferedReader in, PrintWriter out) {
+ try {
+ if (socket != null)
+ socket.close();
+
+ if (in != null)
+ in.close();
+
+ if (out != null)
+ out.close();
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/desktop-client/src/main/java/org/orinprojects/desktop/Main.java b/desktop-client/src/main/java/org/orinprojects/desktop/Main.java
new file mode 100644
index 0000000..741626b
--- /dev/null
+++ b/desktop-client/src/main/java/org/orinprojects/desktop/Main.java
@@ -0,0 +1,46 @@
+package org.orinprojects.desktop;
+
+import javafx.application.Application;
+import javafx.fxml.FXMLLoader;
+import javafx.scene.Parent;
+import javafx.scene.Scene;
+import javafx.stage.Stage;
+import org.orinprojects.encryption.EncryptionUtil;
+
+import javax.crypto.SecretKey;
+import java.io.IOException;
+import java.security.KeyPair;
+import java.security.NoSuchAlgorithmException;
+import java.security.PublicKey;
+
+/**
+ * JavaFX App
+ */
+public class Main extends Application {
+
+ public static KeyPair keys;
+
+ public static PublicKey serverPublicRSA;
+
+ public static SecretKey aesKey;
+
+ @Override
+ public void start(Stage primaryStage) throws IOException, NoSuchAlgorithmException {
+ keys = EncryptionUtil.generateRSAKeys();
+
+ FXMLLoader loader = new FXMLLoader();
+ loader.setLocation(getClass().getResource("/chat.fxml"));
+
+ Parent root = loader.load();
+
+ primaryStage.setTitle("Chat App");
+ primaryStage.setResizable(false);
+ primaryStage.setScene(new Scene(root));
+ primaryStage.show();
+ }
+
+ public static void main(String[] args) {
+ launch();
+ }
+
+}
\ No newline at end of file
diff --git a/desktop-client/src/main/resources/chat.fxml b/desktop-client/src/main/resources/chat.fxml
new file mode 100644
index 0000000..0337c61
--- /dev/null
+++ b/desktop-client/src/main/resources/chat.fxml
@@ -0,0 +1,108 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pom.xml b/pom.xml
index 27e1179..75634ff 100644
--- a/pom.xml
+++ b/pom.xml
@@ -11,6 +11,7 @@
server
client
+ desktop-client
diff --git a/server/src/main/java/module-info.java b/server/src/main/java/module-info.java
new file mode 100644
index 0000000..e2579e4
--- /dev/null
+++ b/server/src/main/java/module-info.java
@@ -0,0 +1,3 @@
+module org.orinprojects.server {
+ exports org.orinprojects.encryption;
+}
\ No newline at end of file
diff --git a/server/src/main/java/org/orinprojects/ClientHandler.java b/server/src/main/java/org/orinprojects/ClientHandler.java
index e475ddd..dd2eaf6 100644
--- a/server/src/main/java/org/orinprojects/ClientHandler.java
+++ b/server/src/main/java/org/orinprojects/ClientHandler.java
@@ -5,15 +5,14 @@ import org.orinprojects.encryption.EncryptionUtil;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
-import java.io.*;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
import java.net.Socket;
-import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
-import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
-import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
-import java.security.spec.X509EncodedKeySpec;
public class ClientHandler implements Runnable {
@@ -64,6 +63,12 @@ public class ClientHandler implements Runnable {
if (prefix.equals("WLC")) {
this.username = restMessage;
+ //TODO: add better logic
+ if (Server.clientKeys.get(username) != null) {
+ in.close();
+ out.close();
+ clientSocket.close();
+ }
continue;
}