Step 2
This commit is contained in:
108
src/main/java/step2/Main.java
Normal file
108
src/main/java/step2/Main.java
Normal 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();
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user