This commit is contained in:
Matthias Guillitte
2025-10-29 14:42:23 +01:00
parent 573b5e48d2
commit 26e45da333

View File

@@ -0,0 +1,108 @@
package step2;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.util.Base64;
import static common.Logger.*;
import static common.SocketManager.*;
public class Main {
private static final String PASSPHRASE = "laPassphrasePartagee";
private static final int PBKDF2_ITERATION = 600_000;
private static final int KEY_LEN_BITS = 256;
public static void main(String[] args){
int port = 8888;
if (args.length >= 2 && args[0].equals("--port")) {
port = Integer.parseInt(args[1]);
}
try (ServerSocket socket = new ServerSocket(port)) {
displayInfo("Server is running on port " + port + "\n waiting for the client to connect...");
while (true) {
try {
handleClient(socket.accept());
return;
} catch (IOException ignored) {}
}
} catch (Exception e) {
e.printStackTrace();
}
}
private static void handleClient(Socket socket) throws IOException, GeneralSecurityException {
socket.setSoTimeout(30000);
displayInfo("Client connected");
// Welcome message
send(socket, "Welcome to the phase 2 server!");
BufferedReader reader = new BufferedReader(
new InputStreamReader(socket.getInputStream())
);
// Reçois le message chiffré et les éléments permettant de dériver la clé
String lineSalt = readResponse(reader);
String lineIv = readResponse(reader);
String lineCt = readResponse(reader);
displayReceived("Salt: " + lineSalt);
displayReceived("IV: " + lineIv);
displayReceived("Ciphered text: " + lineCt);
byte[] salt = Base64.getDecoder().decode(lineSalt.substring(5).trim());
byte[] iv = Base64.getDecoder().decode(lineIv.substring(3).trim());
byte[] ct = Base64.getDecoder().decode(lineCt.substring(3).trim());
// Dérivation clé PBKDF2-HMAC-SHA256 en 256 bits à partir des éléments reçus et de la passphrase commune
byte[] derivedKey = deriveKeyPBKDF2(PASSPHRASE.toCharArray(), salt, PBKDF2_ITERATION, KEY_LEN_BITS);
// Déchiffrement du message avec AES/CBC/PKCS5Padding
String message = decryptAesCbcPkcs5(derivedKey, iv, ct);
displayInfo("Decrypted message: " + message);
// Calcul du TAG : SHA3-256( key || message || "that's all folks" )
byte[] tag = computeSha3_256(derivedKey, message.getBytes(StandardCharsets.UTF_8), "that's all folks".getBytes(StandardCharsets.UTF_8));
String tagB64 = Base64.getEncoder().encodeToString(tag);
// Envoie le TAG au client
send(socket, "TAG:" + tagB64);
displaySent("Tag: " + tagB64);
// Client should OK/KO but doesn't ?
}
private static byte[] deriveKeyPBKDF2(char[] passphrase, byte[] salt, int iterations, int keyLenBits) throws NoSuchAlgorithmException, InvalidKeySpecException {
PBEKeySpec spec = new PBEKeySpec(passphrase, salt, iterations, keyLenBits);
SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
SecretKey key = skf.generateSecret(spec);
return key.getEncoded();
}
private static String decryptAesCbcPkcs5(byte[] keyBytes, byte[] ivBytes, byte[] ciphertext) throws GeneralSecurityException, UnsupportedEncodingException {
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
byte[] plain = cipher.doFinal(ciphertext);
return new String(plain, StandardCharsets.UTF_8);
}
private static byte[] computeSha3_256(byte[] keyPart, byte[] messageBytes, byte[] suffix) throws NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance("SHA3-256");
md.update(keyPart);
md.update(messageBytes);
md.update(suffix);
return md.digest();
}
}