diff --git a/client/src/main/java/org/orinprojects/client/Client.java b/client/src/main/java/org/orinprojects/client/Client.java index 18e5e25..b8d5319 100644 --- a/client/src/main/java/org/orinprojects/client/Client.java +++ b/client/src/main/java/org/orinprojects/client/Client.java @@ -19,6 +19,8 @@ public class Client { static SecretKey aesKey; + static byte[] ivKey; + public static void main(String[] args) throws Exception { Map validatedArguments = getValidatedDataFromArguments(args); @@ -50,7 +52,7 @@ public class Client { System.out.println("Wait for complete initialisation!"); if (client.rsaReceived && client.aesReceived) { - String encryptedText = EncryptionUtil.encryptWithAES(inputText, aesKey); + String encryptedText = EncryptionUtil.encryptWithAES(inputText, aesKey, ivKey); client.out.println("TXT" + encryptedText); client.out.flush(); } diff --git a/client/src/main/java/org/orinprojects/client/ClientThread.java b/client/src/main/java/org/orinprojects/client/ClientThread.java index e00b22c..3986e47 100644 --- a/client/src/main/java/org/orinprojects/client/ClientThread.java +++ b/client/src/main/java/org/orinprojects/client/ClientThread.java @@ -10,6 +10,7 @@ import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket; +import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.spec.InvalidKeySpecException; @@ -53,12 +54,18 @@ public class ClientThread implements Runnable { continue; } + if (prefix.equals("IVK")) { + String decryptedIVKey = EncryptionUtil.decryptWithRSA(restMessage, Client.keys.getPrivate()); + Client.ivKey = EncryptionUtil.ivKeyFromString(decryptedIVKey); + continue; + } + if (prefix.equals("TXT") && aesReceived && rsaReceived) { - String decryptedMessage = EncryptionUtil.decryptWithAES(restMessage, Client.aesKey); + String decryptedMessage = EncryptionUtil.decryptWithAES(restMessage, Client.aesKey, Client.ivKey); System.out.println(decryptedMessage); } } catch (NoSuchPaddingException | IllegalBlockSizeException | IOException | NoSuchAlgorithmException | - InvalidKeySpecException | BadPaddingException | InvalidKeyException e) { + InvalidKeySpecException | BadPaddingException | InvalidKeyException | InvalidAlgorithmParameterException e) { System.out.println("Disconnected from server!"); System.exit(-1); closeAllConnections(clientSocket, in, out); diff --git a/desktop-client/src/main/java/org/orinprojects/desktop/ChatController.java b/desktop-client/src/main/java/org/orinprojects/desktop/ChatController.java index 876b279..4b7c1eb 100644 --- a/desktop-client/src/main/java/org/orinprojects/desktop/ChatController.java +++ b/desktop-client/src/main/java/org/orinprojects/desktop/ChatController.java @@ -16,6 +16,7 @@ import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import java.io.IOException; import java.net.Socket; +import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; @@ -88,12 +89,12 @@ public class ChatController { sendMsgBtn.setDisable(true); } - public void sendMessage() throws IllegalBlockSizeException, NoSuchPaddingException, BadPaddingException, NoSuchAlgorithmException, InvalidKeyException { + public void sendMessage() throws IllegalBlockSizeException, NoSuchPaddingException, BadPaddingException, NoSuchAlgorithmException, InvalidKeyException, InvalidAlgorithmParameterException { if (!clientThread.aesReceived && !clientThread.rsaReceived) System.out.println("Wait for complete initialisation!"); if (clientThread.rsaReceived && clientThread.aesReceived) { - String encryptedText = EncryptionUtil.encryptWithAES(messageTextInput.getText(), aesKey); + String encryptedText = EncryptionUtil.encryptWithAES(messageTextInput.getText(), aesKey, Main.ivKey); clientThread.out.println("TXT" + encryptedText); clientThread.out.flush(); } diff --git a/desktop-client/src/main/java/org/orinprojects/desktop/ClientThread.java b/desktop-client/src/main/java/org/orinprojects/desktop/ClientThread.java index 6a8ded1..92c1fbf 100644 --- a/desktop-client/src/main/java/org/orinprojects/desktop/ClientThread.java +++ b/desktop-client/src/main/java/org/orinprojects/desktop/ClientThread.java @@ -16,6 +16,7 @@ import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket; +import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.spec.InvalidKeySpecException; @@ -65,8 +66,14 @@ public class ClientThread implements Runnable { continue; } + if (prefix.equals("IVK")) { + String decryptedIVKey = EncryptionUtil.decryptWithRSA(restMessage, Main.keys.getPrivate()); + Main.ivKey = EncryptionUtil.ivKeyFromString(decryptedIVKey); + continue; + } + if (prefix.equals("TXT") && aesReceived && rsaReceived) { - String decryptedMessage = EncryptionUtil.decryptWithAES(restMessage, Main.aesKey); + String decryptedMessage = EncryptionUtil.decryptWithAES(restMessage, Main.aesKey, Main.ivKey); Label text = new Label(decryptedMessage); text.setFont(new Font(14)); @@ -75,7 +82,7 @@ public class ClientThread implements Runnable { Platform.runLater(() -> messagesBox.getChildren().add(text)); } } catch (NoSuchPaddingException | IllegalBlockSizeException | IOException | NoSuchAlgorithmException | - InvalidKeySpecException | BadPaddingException |InvalidKeyException e) { + InvalidKeySpecException | BadPaddingException |InvalidKeyException | InvalidAlgorithmParameterException e) { System.err.println("Disconnected from server!"); System.exit(-1); closeAllConnections(clientSocket, in, out); diff --git a/desktop-client/src/main/java/org/orinprojects/desktop/Main.java b/desktop-client/src/main/java/org/orinprojects/desktop/Main.java index d73ddf9..a092c77 100644 --- a/desktop-client/src/main/java/org/orinprojects/desktop/Main.java +++ b/desktop-client/src/main/java/org/orinprojects/desktop/Main.java @@ -24,6 +24,8 @@ public class Main extends Application { static SecretKey aesKey; + static byte[] ivKey; + @Override public void start(Stage primaryStage) throws IOException, NoSuchAlgorithmException { keys = EncryptionUtil.generateRSAKeys(); diff --git a/server/src/main/java/org/orinprojects/ClientHandler.java b/server/src/main/java/org/orinprojects/ClientHandler.java index dd2eaf6..98c73bd 100644 --- a/server/src/main/java/org/orinprojects/ClientHandler.java +++ b/server/src/main/java/org/orinprojects/ClientHandler.java @@ -57,6 +57,11 @@ public class ClientHandler implements Runnable { out.println("AES" + encryptedAES); out.flush(); + String encodedIVKey = EncryptionUtil.ivKeyToString(Server.ivKey); + String encryptedIVKey = EncryptionUtil.encryptWithRSA(encodedIVKey, Server.clientKeys.get(username)); + out.println("IVK" + encryptedIVKey); + out.flush(); + aesSent = true; continue; } @@ -64,11 +69,11 @@ 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(); - } +// if (Server.clientKeys.get(username) != null) { +// in.close(); +// out.close(); +// clientSocket.close(); +// } continue; } diff --git a/server/src/main/java/org/orinprojects/Server.java b/server/src/main/java/org/orinprojects/Server.java index 6aa583a..232cc03 100644 --- a/server/src/main/java/org/orinprojects/Server.java +++ b/server/src/main/java/org/orinprojects/Server.java @@ -29,8 +29,11 @@ public class Server { static SecretKey aesKey; + static byte[] ivKey; + public static void main(String[] args) throws IOException, ArgumentsException, NoSuchAlgorithmException { Server.serverKeys = EncryptionUtil.generateRSAKeys(); + Server.ivKey = EncryptionUtil.generateIV(); Server.aesKey = EncryptionUtil.generateAESKey(); int portNumber = getPortNumber(args); diff --git a/server/src/main/java/org/orinprojects/encryption/EncryptionUtil.java b/server/src/main/java/org/orinprojects/encryption/EncryptionUtil.java index 6ce2f11..711aade 100644 --- a/server/src/main/java/org/orinprojects/encryption/EncryptionUtil.java +++ b/server/src/main/java/org/orinprojects/encryption/EncryptionUtil.java @@ -1,6 +1,7 @@ package org.orinprojects.encryption; import javax.crypto.*; +import javax.crypto.spec.GCMParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.security.*; import java.security.spec.InvalidKeySpecException; @@ -10,10 +11,14 @@ import java.util.Base64; public class EncryptionUtil { - public static final int RSA_KEY_SIZE = 2048; + public static final int RSA_KEY_SIZE = 4096; public static final int AES_KEY_SIZE = 256; + public static final int GCM_IV_LENGTH = 12; + + public static final int GCM_TAG_LENGTH = 16; + private EncryptionUtil() throws IllegalAccessException { throw new IllegalAccessException("Can't be instantiated"); } @@ -73,18 +78,34 @@ public class EncryptionUtil { return keyGenerator.generateKey(); } - public static String encryptWithAES(String plainText, SecretKey aesKey) throws IllegalBlockSizeException, BadPaddingException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException { - Cipher aesChiper = Cipher.getInstance("AES"); - aesChiper.init(Cipher.ENCRYPT_MODE, aesKey); + public static byte[] generateIV() { + byte[] iv = new byte[GCM_IV_LENGTH]; + SecureRandom random = new SecureRandom(); + random.nextBytes(iv); + + return iv; + } + + public static String encryptWithAES(String plainText, SecretKey aesKey, byte[] ivKey) throws IllegalBlockSizeException, BadPaddingException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, InvalidAlgorithmParameterException { + Cipher aesChiper = Cipher.getInstance("AES/GCM/NoPadding"); + + SecretKeySpec keySpec = new SecretKeySpec(aesKey.getEncoded(), "AES"); + GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(GCM_TAG_LENGTH * 8, ivKey); + + aesChiper.init(Cipher.ENCRYPT_MODE, keySpec, gcmParameterSpec); byte[] byteCipherText = aesChiper.doFinal(plainText.getBytes()); return Base64.getEncoder().encodeToString(byteCipherText); } - public static String decryptWithAES(String encryptedMessage, SecretKey aesKey) throws IllegalBlockSizeException, BadPaddingException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException { - Cipher aesChiper = Cipher.getInstance("AES"); - aesChiper.init(Cipher.DECRYPT_MODE, aesKey); + public static String decryptWithAES(String encryptedMessage, SecretKey aesKey, byte[] ivKey) throws IllegalBlockSizeException, BadPaddingException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, InvalidAlgorithmParameterException { + Cipher aesChiper = Cipher.getInstance("AES/GCM/NoPadding"); + + SecretKeySpec keySpec = new SecretKeySpec(aesKey.getEncoded(), "AES"); + GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(GCM_TAG_LENGTH * 8, ivKey); + + aesChiper.init(Cipher.DECRYPT_MODE, keySpec, gcmParameterSpec); byte[] byteCipherText = aesChiper.doFinal(Base64.getDecoder().decode(encryptedMessage)); @@ -100,4 +121,11 @@ public class EncryptionUtil { return Base64.getEncoder().encodeToString(secretKey.getEncoded()); } + public static String ivKeyToString(byte[] iv) { + return Base64.getEncoder().encodeToString(iv); + } + + public static byte[] ivKeyFromString(String ivKey) { + return Base64.getDecoder().decode(ivKey); + } }