diff --git a/src/main/java/acs/acs/src/Main.java b/src/main/java/acs/acs/src/Main.java index e0050e0..0c0597e 100644 --- a/src/main/java/acs/acs/src/Main.java +++ b/src/main/java/acs/acs/src/Main.java @@ -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 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 Luhn Algorithm + * @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); + } + } diff --git a/src/main/java/acs/acs/src/TokenManager.java b/src/main/java/acs/acs/src/TokenManager.java new file mode 100644 index 0000000..259b6a3 --- /dev/null +++ b/src/main/java/acs/acs/src/TokenManager.java @@ -0,0 +1,19 @@ +package acs.acs.src; + +import common.common.src.crypto.CryptoUtils; + +import java.util.HashSet; + +public class TokenManager { + private final HashSet tokens = new HashSet(); + + public String generateAndStoreToken() { + String token = CryptoUtils.generateToken(); + tokens.add(token); + return token; + } + + public boolean isValidToken(String token) { + return tokens.contains(token); + } +} diff --git a/src/main/java/externalApp/externalApp/src/Main.java b/src/main/java/externalApp/externalApp/src/Main.java index 2609aa7..d4df166 100644 --- a/src/main/java/externalApp/externalApp/src/Main.java +++ b/src/main/java/externalApp/externalApp/src/Main.java @@ -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"); }