From d0eb17f7728c1e7b5799c0fba03f87020dfe1e6b Mon Sep 17 00:00:00 2001 From: Laurent Date: Fri, 24 Oct 2025 19:32:34 +0200 Subject: [PATCH] Step 1 completed --- src/main/java/step1/Main.java | 103 ++++++++++++++++++++++++++-------- 1 file changed, 80 insertions(+), 23 deletions(-) diff --git a/src/main/java/step1/Main.java b/src/main/java/step1/Main.java index af2b86b..b003496 100644 --- a/src/main/java/step1/Main.java +++ b/src/main/java/step1/Main.java @@ -3,6 +3,7 @@ package step1; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; +import javax.crypto.spec.GCMParameterSpec; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.io.*; @@ -23,7 +24,6 @@ public class Main { try (Socket socket = new Socket()) { - socket.connect(new InetSocketAddress("127.0.0.1", 8888)); //Saving the buffer reference to read it later @@ -33,40 +33,78 @@ public class Main { //Waiting for welcome message so it does //not pollute the fucking stream String welcome = readResponse(reader); - System.out.println("Welcome message: " + welcome); + displayReceived("Welcome message: " + welcome); //Creating the key SecretKey key = get3DESKey(); byte[] encodedKey = key.getEncoded(); String base64Key = Base64.getEncoder().encodeToString(encodedKey); + displayInfo("Generated key: " + base64Key); //Sending the key send(socket, base64Key); - System.out.println("Key sent to server."); + displaySent("Key sent to server : " + base64Key); //Reading the message sent by the server String text = readResponse(reader); - System.out.println("Received message: " + text); + displayReceived("Received message: " + text); //Encrypting the message byte[] encryptedMessage = encrypt(key, text); String base64Message = Base64.getEncoder().encodeToString(encryptedMessage); - System.out.println("Encrypted message to send : " + base64Message); + displayInfo("Encrypted message : " + base64Message); //Sending encrypted message send(socket, base64Message); - System.out.println("Encrypted message sent to server."); + displaySent("Encrypted message sent to server : " + base64Message); - //Reading the parameters sent by the server - String parameters = readResponse(reader); - System.out.println("Received parameters: " + parameters); + //Reading the base 64 key sent by the server + String receivedKey = readResponse(reader); + displayReceived("Received base64 key: " + receivedKey); + //Reading the base 64 IV sent by the server + String base64IV = readResponse(reader); + displayReceived("Received base 64 IV: " + base64IV); + + //Reading the AAD sent by the server + String AAD = readResponse(reader); + displayReceived("Received AAD: " + AAD); + + //Reading the base 64 encrypted message sent by the server + String base64ReceivedMessage = readResponse(reader); + displayReceived("Received base 64 encrypted message: " + base64ReceivedMessage); + + String decryptedMessage = decrypt(receivedKey, base64IV, AAD, base64ReceivedMessage); + displayInfo("Decrypted message : " + decryptedMessage); + + send(socket, decryptedMessage); + displaySent("Decrypted message sent to server : " + decryptedMessage); + + displayInfo("Process completed. Check out the server output to know if it was successful."); } catch (Exception e) { e.printStackTrace(); } } + public static void displayInfo(String message){ + final String BLUE = "\u001B[34m"; + final String RESET = "\u001B[0m"; + System.out.println(BLUE + "Info >>> " + message + RESET); + } + + public static void displayReceived(String message){ + String GREEN = "\u001B[32m"; + String RESET = "\u001B[0m"; + System.out.println(GREEN + "Received >>> " + message + RESET); + } + + public static void displaySent(String message){ + final String RED = "\u001B[31m"; + final String RESET = "\u001B[0m"; + System.out.println(RED + "Sent >>> " + message + RESET); + } + public static void send(Socket socket, String data) throws IOException { OutputStream output = socket.getOutputStream(); output.write(String.format("%s\r\n", data).getBytes(StandardCharsets.UTF_8)); @@ -91,24 +129,43 @@ public class Main { } - public static String decrypt(byte[] keyBytes, String base64IvAndCiphertext) throws Exception { - SecretKey key = new SecretKeySpec(keyBytes, ALGORITHM); + public static String decrypt(String base64Key, String base64IV, String aad, String base64Ciphertext) throws Exception { - byte[] ivPlusCipher = Base64.getDecoder().decode(base64IvAndCiphertext); - if (ivPlusCipher.length < 8) throw new IllegalArgumentException("Data too short"); + final int GCM_TAG_LENGTH = 128; - byte[] iv = new byte[8]; - System.arraycopy(ivPlusCipher, 0, iv, 0, 8); - IvParameterSpec ivSpec = new IvParameterSpec(iv); + // Decode Base64 inputs + byte[] key = Base64.getDecoder().decode(base64Key); + byte[] iv = Base64.getDecoder().decode(base64IV); + byte[] cipherMessage = Base64.getDecoder().decode(base64Ciphertext); - byte[] ciphertext = new byte[ivPlusCipher.length - 8]; - System.arraycopy(ivPlusCipher, 8, ciphertext, 0, ciphertext.length); + // Split ciphertext and authentication tag (last 16 bytes) + int tagLength = GCM_TAG_LENGTH / 8; + int ciphertextLength = cipherMessage.length - tagLength; + byte[] ciphertext = new byte[ciphertextLength]; + byte[] tag = new byte[tagLength]; - Cipher cipher = Cipher.getInstance(TRANSFORMATION); - cipher.init(Cipher.DECRYPT_MODE, key, ivSpec); + System.arraycopy(cipherMessage, 0, ciphertext, 0, ciphertextLength); + System.arraycopy(cipherMessage, ciphertextLength, tag, 0, tagLength); - byte[] plaintextBytes = cipher.doFinal(ciphertext); - return new String(plaintextBytes, StandardCharsets.UTF_8); + // Combine ciphertext + tag + byte[] ciphertextWithTag = new byte[cipherMessage.length]; + System.arraycopy(cipherMessage, 0, ciphertextWithTag, 0, cipherMessage.length); + + // Create AES key and GCM spec + SecretKeySpec keySpec = new SecretKeySpec(key, "AES"); + GCMParameterSpec gcmSpec = new GCMParameterSpec(GCM_TAG_LENGTH, iv); + + // Initialize cipher + Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); + cipher.init(Cipher.DECRYPT_MODE, keySpec, gcmSpec); + + // Add AAD (if any) + if (aad != null && !aad.isEmpty()) { + cipher.updateAAD(aad.getBytes()); + } + + // Decrypt and return plaintext + byte[] plaintext = cipher.doFinal(ciphertextWithTag); + return new String(plaintext, "UTF-8"); } - } \ No newline at end of file