Compare commits
10 Commits
d0eb17f772
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8253ea2d2e | ||
|
|
3c0e94cb35 | ||
|
|
fa02d69063 | ||
|
|
05a25ba761 | ||
|
|
c44f31a8ea | ||
|
|
67115b9693 | ||
|
|
1f76926cbb | ||
|
|
0ba3aa76cf | ||
|
|
26e45da333 | ||
|
|
573b5e48d2 |
@@ -1 +1,3 @@
|
||||
Thanks, you read me
|
||||
### Commands to launch autoGrader
|
||||
- cd ~/autoGrader/
|
||||
- java -jar <autoGrader_name>.jar
|
||||
Binary file not shown.
@@ -2,6 +2,55 @@ plugins {
|
||||
id("java")
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
create("common") {
|
||||
java.srcDir("src/main/java/common")
|
||||
}
|
||||
|
||||
// Step1-3 each depend on common
|
||||
create("step1") {
|
||||
java.srcDirs("src/main/java/common", "src/main/java/step1")
|
||||
}
|
||||
create("step2") {
|
||||
java.srcDirs("src/main/java/common", "src/main/java/step2")
|
||||
}
|
||||
create("step3") {
|
||||
java.srcDirs("src/main/java/common", "src/main/java/step3")
|
||||
}
|
||||
}
|
||||
|
||||
// === Create JAR tasks for each step ===
|
||||
tasks.register<Jar>("jarStep1") {
|
||||
manifest {
|
||||
attributes["Main-Class"] = "step1.Main"
|
||||
}
|
||||
archiveBaseName.set("step1")
|
||||
from(sourceSets["step1"].output)
|
||||
dependsOn("classes")
|
||||
}
|
||||
|
||||
tasks.register<Jar>("jarStep2") {
|
||||
manifest {
|
||||
attributes["Main-Class"] = "step2.Main"
|
||||
}
|
||||
archiveBaseName.set("step2")
|
||||
from(sourceSets["step2"].output)
|
||||
dependsOn("classes")
|
||||
}
|
||||
|
||||
tasks.register<Jar>("jarStep3") {
|
||||
manifest {
|
||||
attributes["Main-Class"] = "step3.Main"
|
||||
}
|
||||
archiveBaseName.set("step3")
|
||||
from(sourceSets["step3"].output)
|
||||
dependsOn("classes")
|
||||
}
|
||||
|
||||
tasks.named("build") {
|
||||
dependsOn("jarStep1", "jarStep2", "jarStep3")
|
||||
}
|
||||
|
||||
group = "be.naaturel"
|
||||
version = "1.0-SNAPSHOT"
|
||||
|
||||
|
||||
21
src/main/java/common/Logger.java
Normal file
21
src/main/java/common/Logger.java
Normal file
@@ -0,0 +1,21 @@
|
||||
package common;
|
||||
|
||||
public class Logger {
|
||||
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);
|
||||
}
|
||||
}
|
||||
19
src/main/java/common/SocketManager.java
Normal file
19
src/main/java/common/SocketManager.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package common;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.net.Socket;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class SocketManager {
|
||||
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));
|
||||
output.flush();
|
||||
}
|
||||
|
||||
public static String readResponse(BufferedReader reader) throws IOException {
|
||||
return reader.readLine();
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,11 @@ import java.security.NoSuchAlgorithmException;
|
||||
import java.security.NoSuchProviderException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Base64;
|
||||
import static common.Logger.displayInfo;
|
||||
import static common.Logger.displayReceived;
|
||||
import static common.Logger.displaySent;
|
||||
import static common.SocketManager.send;
|
||||
import static common.SocketManager.readResponse;
|
||||
|
||||
public class Main {
|
||||
|
||||
@@ -87,34 +92,6 @@ public class Main {
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
output.flush();
|
||||
}
|
||||
|
||||
public static String readResponse(BufferedReader reader) throws IOException {
|
||||
return reader.readLine();
|
||||
}
|
||||
|
||||
public static SecretKey get3DESKey() throws NoSuchAlgorithmException, NoSuchProviderException {
|
||||
KeyGenerator keyGen = KeyGenerator.getInstance(ALGORITHM, PROVIDER);
|
||||
keyGen.init(new SecureRandom());
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
257
src/main/java/step3/Main.java
Normal file
257
src/main/java/step3/Main.java
Normal file
@@ -0,0 +1,257 @@
|
||||
package step3;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.math.BigInteger;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.PublicKey;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.Signature;
|
||||
import java.security.spec.MGF1ParameterSpec;
|
||||
import java.security.spec.PSSParameterSpec;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
import java.util.Arrays;
|
||||
import java.util.Base64;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.SecretKeyFactory;
|
||||
import javax.crypto.spec.GCMParameterSpec;
|
||||
import javax.crypto.spec.PBEKeySpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
import static common.Logger.displayInfo;
|
||||
import static common.Logger.displayReceived;
|
||||
import static common.Logger.displaySent;
|
||||
import static common.SocketManager.readResponse;
|
||||
import static common.SocketManager.send;
|
||||
|
||||
public class Main {
|
||||
|
||||
private static final BigInteger P = new BigInteger("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16);
|
||||
private static final BigInteger G = new BigInteger("2", 16);
|
||||
|
||||
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");
|
||||
|
||||
BufferedReader reader = new BufferedReader(
|
||||
new InputStreamReader(socket.getInputStream())
|
||||
);
|
||||
|
||||
String message = readResponse(reader);
|
||||
displayReceived("Received A : " + message);
|
||||
byte[] A_bytes = Base64.getDecoder().decode(message.substring(2));
|
||||
BigInteger A = new BigInteger(1, A_bytes);
|
||||
|
||||
// Compute b and B
|
||||
BigInteger b = new BigInteger(256, new java.security.SecureRandom());
|
||||
BigInteger B = G.modPow(b, P);
|
||||
byte[] B_bytes = toFixedLen(B, 256);
|
||||
|
||||
// Send B
|
||||
message = "B:" + Base64.getEncoder().encodeToString(B_bytes);
|
||||
send(socket, message);
|
||||
displaySent("B sent : " + message);
|
||||
|
||||
// Compute shared Z
|
||||
|
||||
BigInteger Z = A.modPow(b, P);
|
||||
byte[] Z_bytes = toFixedLen(Z, 256);
|
||||
|
||||
// compute PBKDF-HMAC key
|
||||
|
||||
byte[] key = PBKDF_HMAC_key(A, B, P, G);
|
||||
|
||||
byte[] nonce = new byte[12];
|
||||
new java.security.SecureRandom().nextBytes(nonce);
|
||||
|
||||
// Generate RSA 2048-bit key pair
|
||||
KeyPair rsaKP = generateRSAKeyPair();
|
||||
|
||||
// Encrypt the RSA public key (X.509 DER) with AES-GCM using the derived key
|
||||
byte[] pubBytes = rsaKP.getPublic().getEncoded();
|
||||
|
||||
// Calculer l'AAD (Additional Authenticated Data)
|
||||
byte[] aad = AES_GCM(A, B, P, G); // retourne SHA-256(g || p || A || B)
|
||||
|
||||
// Chiffrer avec AAD
|
||||
SecretKeySpec aesKeySpec = new SecretKeySpec(key, "AES");
|
||||
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
|
||||
GCMParameterSpec gcmSpec = new GCMParameterSpec(128, nonce);
|
||||
cipher.init(Cipher.ENCRYPT_MODE, aesKeySpec, gcmSpec);
|
||||
cipher.updateAAD(aad); // <-- Ajouter l'AAD AVANT doFinal
|
||||
byte[] ciphertext = cipher.doFinal(pubBytes);
|
||||
|
||||
// Assemble nonce || ciphertext and Base64-encode
|
||||
byte[] out = new byte[nonce.length + ciphertext.length];
|
||||
System.arraycopy(nonce, 0, out, 0, nonce.length);
|
||||
System.arraycopy(ciphertext, 0, out, nonce.length, ciphertext.length);
|
||||
String payloadB64 = Base64.getEncoder().encodeToString(out);
|
||||
|
||||
message = "PUBS:" + payloadB64;
|
||||
send(socket, message);
|
||||
displaySent("PUBS sent : " + message);
|
||||
|
||||
// Read client's encrypted public key (PUBC) and encrypted RSA ciphertext (CT_RSA)
|
||||
String PUBC = readResponse(reader);
|
||||
displayReceived("Received PUBC : " + PUBC);
|
||||
|
||||
String CT_RSA = readResponse(reader);
|
||||
displayReceived("Received CT_RSA : " + CT_RSA);
|
||||
|
||||
// Decrypt PUBC: format PUBC:<base64(nonce||ciphertext)>
|
||||
byte[] pubcDecoded = Base64.getDecoder().decode(PUBC.substring(5));
|
||||
if (pubcDecoded.length < 12) throw new IOException("PUBC too short");
|
||||
byte[] pubcNonce = Arrays.copyOfRange(pubcDecoded, 0, 12);
|
||||
byte[] pubcCt = Arrays.copyOfRange(pubcDecoded, 12, pubcDecoded.length);
|
||||
|
||||
// Decrypt client's public key with AES-GCM
|
||||
GCMParameterSpec pubcGcm = new GCMParameterSpec(128, pubcNonce);
|
||||
Cipher aesDec = Cipher.getInstance("AES/GCM/NoPadding");
|
||||
aesDec.init(Cipher.DECRYPT_MODE, aesKeySpec, pubcGcm);
|
||||
aesDec.updateAAD(aad);
|
||||
byte[] clientPubBytes = aesDec.doFinal(pubcCt);
|
||||
|
||||
// Recreate client's RSA PublicKey
|
||||
KeyFactory kf = KeyFactory.getInstance("RSA");
|
||||
PublicKey clientPub = kf.generatePublic(new X509EncodedKeySpec(clientPubBytes));
|
||||
|
||||
// Decrypt CT_RSA which is RSA-OAEP encrypted with server's public key (so server uses private key)
|
||||
byte[] ctRsaDecoded = Base64.getDecoder().decode(CT_RSA.substring(CT_RSA.indexOf(':')+1));
|
||||
Cipher rsaDec = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
|
||||
rsaDec.init(Cipher.DECRYPT_MODE, rsaKP.getPrivate());
|
||||
byte[] Mbytes = rsaDec.doFinal(ctRsaDecoded);
|
||||
|
||||
// Sign M with RSASSA-PSS (SHA-256, MGF1(SHA-256), saltLen=32)
|
||||
Signature signer = Signature.getInstance("RSASSA-PSS");
|
||||
PSSParameterSpec pssSpec = new PSSParameterSpec("SHA-256", "MGF1", new MGF1ParameterSpec("SHA-256"), 32, 1);
|
||||
signer.setParameter(pssSpec);
|
||||
signer.initSign(rsaKP.getPrivate(), new SecureRandom());
|
||||
signer.update(Mbytes);
|
||||
byte[] signature = signer.sign();
|
||||
|
||||
// Split signature into 2 chunks of 128 bytes
|
||||
byte[] sig1 = Arrays.copyOfRange(signature, 0, 128);
|
||||
byte[] sig2 = Arrays.copyOfRange(signature, 128, 256);
|
||||
|
||||
// Encrypt each chunk with client's public key using RSA/OAEP (SHA-256)
|
||||
Cipher rsaEnc = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
|
||||
rsaEnc.init(Cipher.ENCRYPT_MODE, clientPub);
|
||||
byte[] encSig1 = rsaEnc.doFinal(sig1);
|
||||
byte[] encSig2 = rsaEnc.doFinal(sig2);
|
||||
// Send two messages (labels SIG1 and SIG2)
|
||||
String sig1B64 = Base64.getEncoder().encodeToString(encSig1);
|
||||
String sig2B64 = Base64.getEncoder().encodeToString(encSig2);
|
||||
|
||||
send(socket, "SIG1:" + sig1B64);
|
||||
displaySent("SIG1 sent");
|
||||
|
||||
send(socket, "SIG2:" + sig2B64);
|
||||
displaySent("SIG2 sent");
|
||||
}
|
||||
|
||||
private static byte[] toFixedLen(BigInteger x, int len) {
|
||||
byte[] t = x.toByteArray();
|
||||
if (t.length == len) return t;
|
||||
if (t[0] == 0 && t.length == len + 1) { // strip leading zero
|
||||
byte[] r = new byte[len];
|
||||
System.arraycopy(t, 1, r, 0, len);
|
||||
return r;
|
||||
}
|
||||
byte[] r = new byte[len];
|
||||
System.arraycopy(t, Math.max(0, t.length - len), r, len - Math.min(len, t.length),
|
||||
Math.min(len, t.length));
|
||||
return r;
|
||||
}
|
||||
|
||||
private static byte[] PBKDF_HMAC_key(BigInteger A, BigInteger B, BigInteger p, BigInteger g) throws GeneralSecurityException, IOException {
|
||||
|
||||
// Build the concatenation: g as 1 byte, p/A/B as 256 bytes each
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
outputStream.write(toFixedLen(g, 1));
|
||||
outputStream.write(toFixedLen(p, 256));
|
||||
outputStream.write(toFixedLen(A, 256));
|
||||
outputStream.write(toFixedLen(B, 256));
|
||||
|
||||
byte[] concat = outputStream.toByteArray();
|
||||
|
||||
// SHA-256 over the concatenation
|
||||
MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
|
||||
byte[] digest = sha256.digest(concat);
|
||||
|
||||
// passphrase = Base64(SHA-256(...)) as a UTF-8 string (then used as password chars)
|
||||
String passphraseB64 = Base64.getEncoder().encodeToString(digest);
|
||||
char[] passphraseChars = passphraseB64.toCharArray();
|
||||
|
||||
// salt (UTF-8) with trailing space
|
||||
byte[] salt = "phase3 aead key ".getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
PBEKeySpec spec = new PBEKeySpec(passphraseChars, salt, 600000, 256);
|
||||
SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
|
||||
byte[] key = skf.generateSecret(spec).getEncoded();
|
||||
|
||||
// Cleanup sensitive data in memory where practical
|
||||
Arrays.fill(passphraseChars, '\0');
|
||||
spec.clearPassword();
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
private static byte[] AES_GCM(BigInteger A, BigInteger B, BigInteger p, BigInteger g) throws GeneralSecurityException, IOException{
|
||||
|
||||
// Build the concatenation: g as 1 byte, p/A/B as 256 bytes each
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
outputStream.write(toFixedLen(g, 1));
|
||||
outputStream.write(toFixedLen(p, 256));
|
||||
outputStream.write(toFixedLen(A, 256));
|
||||
outputStream.write(toFixedLen(B, 256));
|
||||
|
||||
byte[] concat = outputStream.toByteArray();
|
||||
|
||||
// SHA-256 over the concatenation
|
||||
MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
|
||||
byte[] AAD = sha256.digest(concat);
|
||||
|
||||
|
||||
return AAD;
|
||||
}
|
||||
|
||||
private static KeyPair generateRSAKeyPair() throws GeneralSecurityException {
|
||||
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
|
||||
kpg.initialize(2048, new SecureRandom());
|
||||
return kpg.generateKeyPair();
|
||||
}
|
||||
|
||||
private static String publicKeyToX509Base64(PublicKey pub) {
|
||||
return Base64.getEncoder().encodeToString(pub.getEncoded());
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user