External APP + ACS : Small cleanup + ACS verify card infos + Token Manager

This commit is contained in:
Matthias Guillitte
2025-12-07 15:14:34 +01:00
parent ff34340bdc
commit 64b46c27ee
3 changed files with 91 additions and 11 deletions

View File

@@ -1,5 +1,6 @@
package acs.acs.src;
import acs.acs.src.json.CreditCard;
import acs.acs.src.json.Payload;
import common.common.src.crypto.KeyFactory;
import common.common.src.crypto.CryptoUtils;
@@ -11,13 +12,14 @@ import common.common.src.socket.SocketManager;
import javax.net.ssl.*;
import java.io.IOException;
import java.security.*;
import java.time.LocalDateTime;
import java.time.YearMonth;
import java.util.Base64;
import java.util.Map;
import static common.common.src.ports.Ports.ACS_SERVER_PORT;
import static common.common.src.ports.Ports.AUTH_PORT;
public class Main {
private static final String KEY_STORE_PATH = "assets/certs/acs/acs.keystore.p12";
@@ -26,7 +28,7 @@ public class Main {
private static final String TRUST_STORE_PATH = "assets/certs/acs/acs.truststore.p12";
private static final String TRUST_STORE_PWD = "hepl_truststore";
private static String generatedToken;
private static final TokenManager tokenManager = new TokenManager();
public static void main(String[] args) throws Exception {
@@ -51,6 +53,9 @@ public class Main {
String response = SocketManager.readResponse(clientSocket);
Logger.displayReceived(response);
String token = "TODO : extract token from response";
String answer = tokenManager.isValidToken(token) ? "ACK" : "NAK";
String message = "ACK from ACS";
SocketManager.send(clientSocket, message);
Logger.displaySent("ACK from ACS");
@@ -71,22 +76,75 @@ public class Main {
byte[] signatureBytes = Base64.getDecoder().decode(payload.signature());
if (!CryptoUtils.checkSignature(publicKey, payload.data(), signatureBytes)) {
clientSocket.close();
Logger.displayInfo("Signature NOK");
return;
}
Logger.displayInfo("Signature OK");
// Vérification des informations bancaires
CreditCard creditCard = JsonManager.deserialize(payload.data(), CreditCard.class);
if (!checkCardDetails(creditCard.number(), creditCard.expirationDate())) {
clientSocket.close();
Logger.displayInfo("Détails de la carte NOK");
return;
}
Logger.displayInfo("Détails de la carte OK");
PrivateKey privateKey = CryptoUtils.getPrivateKey(KEY_STORE_PATH, KEY_STORE_PWD, "acs");
String token = CryptoUtils.generateToken();
String token = tokenManager.generateAndStoreToken();
String signedToken = CryptoUtils.signData(privateKey, token);
Map<String, Object> data = Map.of("token", token, "signature", signedToken);
String response = JsonManager.serialize(data);
SocketManager.send(clientSocket, response);
generatedToken = token;
} catch (IOException ioe) {
throw new RuntimeException(ioe);
}
}
/**
* Vérifie les détails de la carte bancaire
* @param cardNumber The credit card number as a String
* @param expirationDate The expiration date in the format "MM/YY"
* @return true if the card details are valid, false otherwise
*/
private static boolean checkCardDetails(String cardNumber, String expirationDate) {
String[] dateParts = expirationDate.split("/");
int month = Integer.parseInt(dateParts[0]);
int year = Integer.parseInt(dateParts[1]) + 2000;
LocalDateTime cardDate = YearMonth.of(year, month).atDay(1).atStartOfDay();
LocalDateTime now = LocalDateTime.now();
// 1. Date d'expiration est future
if (cardDate.isAfter(now)) {
return false;
}
// 2. Numéro de carte valide (Luhn)
return luhnCheck(cardNumber);
}
/**
* @see <a href="https://www.baeldung.com/java-validate-cc-number">Luhn Algorithm</a>
* @param cardNumber The credit card number as a String
* @return true if the card number is valid according to the Luhn algorithm, false otherwise
*/
private static boolean luhnCheck(String cardNumber) {
int sum = 0;
boolean alternate = false;
for (int i = cardNumber.length() - 1; i >= 0; i--) {
int n = Integer.parseInt(cardNumber.substring(i, i + 1));
if (alternate) {
n *= 2;
if (n > 9) {
n = (n % 10) + 1;
}
}
sum += n;
alternate = !alternate;
}
return (sum % 10 == 0);
}
}

View File

@@ -0,0 +1,19 @@
package acs.acs.src;
import common.common.src.crypto.CryptoUtils;
import java.util.HashSet;
public class TokenManager {
private final HashSet<String> tokens = new HashSet<String>();
public String generateAndStoreToken() {
String token = CryptoUtils.generateToken();
tokens.add(token);
return token;
}
public boolean isValidToken(String token) {
return tokens.contains(token);
}
}

View File

@@ -12,13 +12,10 @@ import externalApp.externalApp.src.json.Payload;
import javax.net.ssl.*;
import java.io.*;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.util.Base64;
import java.util.Map;
import static common.common.src.ports.Ports.*;
@@ -33,11 +30,12 @@ public class Main {
public static void main(String[] args) throws IOException, KeyStoreException, UnrecoverableKeyException, NoSuchAlgorithmException, InvalidKeyException, SignatureException, URISyntaxException, CertificateException, KeyManagementException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//String expirationDate = acquireStringInput( br,"Quel est la date d'expiration de la carte de crédit ? (MM/AA)");
//String cardNumber = acquireStringInput(br, "Numéro de la carte de crédit : ");
// String expirationDate = acquireStringInput( br,"Quel est la date d'expiration de la carte de crédit (MM/AA) ? ");
// String cardNumber = acquireStringInput(br, "Numéro de la carte de crédit : ");
String expirationDate = "01/01";
String cardNumber = "0123456789012345";
// String cardNumber = "0123456789012345"; // Invalid card for testing
String cardNumber = "123456789056"; // Valid card for testing
String jsonString = buildCreditCardJson(expirationDate, cardNumber);
@@ -105,12 +103,17 @@ public class Main {
String response = SocketManager.readResponse(socket);
Logger.displayReceived(response);
if (response == null || response.isEmpty()) {
Logger.displayInfo("No response received from ACS.");
return;
}
PublicKey publicKey = CryptoUtils.getPublicKey(TRUST_STORE_PATH, TRUST_STORE_PWD, "acs");
Payload responsePayload = JsonManager.deserialize(response, Payload.class);
byte[] signatureBytes = Base64.getDecoder().decode(responsePayload.signature());
if(CryptoUtils.checkSignature(publicKey, responsePayload.token(), signatureBytes)){
Logger.displayInfo(responsePayload.token());
Logger.displayInfo("Token : " + responsePayload.token());
} else {
Logger.displayInfo("Token NOK");
}