diff --git a/assets/certs/ca.cert.srl b/assets/certs/ca.cert.srl index 9384156..58eff74 100644 --- a/assets/certs/ca.cert.srl +++ b/assets/certs/ca.cert.srl @@ -1 +1 @@ -40DC6F16EBBDE5724552A319CD26F7C16B02ACEE +40DC6F16EBBDE5724552A319CD26F7C16B02ACEF diff --git a/assets/certs/externalApp.cert.pem b/assets/certs/externalApp.cert.pem new file mode 100644 index 0000000..f7af7ae --- /dev/null +++ b/assets/certs/externalApp.cert.pem @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDZTCCAk2gAwIBAgIUQNxvFuu95XJFUqMZzSb3wWsCrO8wDQYJKoZIhvcNAQEL +BQAwUDELMAkGA1UEBhMCQkUxDjAMBgNVBAgMBUxpZWdlMQ4wDAYDVQQHDAVMaWVn +ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMB4XDTI1MTIwMzE0 +NDI1MFoXDTI2MTIwMzE0NDI1MFowRTELMAkGA1UEBhMCQmUxEzARBgNVBAgMClNv +bWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJBRa7imhWweQo0qV1TImqcCX2Rw +IhYIeoVtPKxtwkjgcb6Wj9iHtj3wbfGzGoMH92H4TXHVjgIukSJyUH5RjaMu1f0Z +d9EepZCGLr443NRJwwjf5HSCauiCk7dODe3AzDWiolNoPNDaud6AB+dGKn0Shkzv +pG2MiwAZrUDZijsTYuscRmh9fHMvgVYkSex56xTcXdCQuF0bfvZ1zBwfKwsY/j3Z +6dJRe+5aqCk2clbNjoIqkHNjVOZJKW+Ymi+mN+SjKkDIcW08b6tD3RhCFkuTR6/Q +Oymq+Gy/2hLUIFZZALU4J4s3V6oIUnBi3GMR2hN7Lnd04FDxUR4A7Z00i0UCAwEA +AaNCMEAwHQYDVR0OBBYEFP3mtVOR6kok58eA0hVNKRyf9NCwMB8GA1UdIwQYMBaA +FCvWbKgANSI8XWEaWtWAKUtiMNprMA0GCSqGSIb3DQEBCwUAA4IBAQBMAkUL2pQP +s4i+jtLoHenpz2smTs47jr5plxC7WcMnSwNcu7juu3GvogCB3ee8HCmBPFZ4k2a8 +wZ4gJVOsW1Lstji1dgpJ8bcM2ToXAOnU15+3ym2G1hBoWpp30OjUIDteYF/zqXAP +YloYExUkwVZmxW9IZJR+CXU2wvtc6mR3U6KnyR5Pd/ksTZv11bsxtOw9G4afdGrl +x74wtWsRBebvRDZotlObGRTFXrfhvdaY1+ZT4sepR5bCrkg0PjJvEz74PJWotcPb +ezcuReeo+xfaVuSl/yuCcQCOfOWhVLnLrqUvl08oRNnoQ098E83yXZFKEvSWsRyW +8Opes4zwY9RZ +-----END CERTIFICATE----- diff --git a/assets/certs/externalApp.csr.pem b/assets/certs/externalApp.csr.pem new file mode 100644 index 0000000..0be1b9d --- /dev/null +++ b/assets/certs/externalApp.csr.pem @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIICijCCAXICAQAwRTELMAkGA1UEBhMCQmUxEzARBgNVBAgMClNvbWUtU3RhdGUx +ITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBAJBRa7imhWweQo0qV1TImqcCX2RwIhYIeoVtPKxt +wkjgcb6Wj9iHtj3wbfGzGoMH92H4TXHVjgIukSJyUH5RjaMu1f0Zd9EepZCGLr44 +3NRJwwjf5HSCauiCk7dODe3AzDWiolNoPNDaud6AB+dGKn0ShkzvpG2MiwAZrUDZ +ijsTYuscRmh9fHMvgVYkSex56xTcXdCQuF0bfvZ1zBwfKwsY/j3Z6dJRe+5aqCk2 +clbNjoIqkHNjVOZJKW+Ymi+mN+SjKkDIcW08b6tD3RhCFkuTR6/QOymq+Gy/2hLU +IFZZALU4J4s3V6oIUnBi3GMR2hN7Lnd04FDxUR4A7Z00i0UCAwEAAaAAMA0GCSqG +SIb3DQEBCwUAA4IBAQCBQmHUuJakHI0190O5mZgNsSe/Ml+YJfd1NeQksm/1gOwu +Id+MUdWuVpwAY3W6j8iYZN7IFPmEtlpH77z/CVoAGztPUpp8e3rYGclJOdVNVTuD +jyieLxXUwFmHBh/fAmcoLpt2/V4ltNaT17h3cCkv4A0PwCV9IURv6S5zzO0UnWmB +PHfzGpfN+JtwrDn3MJ4g4v3CjXu9lhL3Hn9fDhEh3pCEHlWZyDMFVg/7ubyVqzAN +FTOfh9laU+8fBy8UqQkznRarfkx7Ce8REnbabKf3sdHxNkO5SzpQJnFBuLT0IiGH +R1M5nA1hwMvJkWVBGVorHDx6vaTAjkcjd7JGaMS2 +-----END CERTIFICATE REQUEST----- diff --git a/assets/certs/externalApp.jks b/assets/certs/externalApp.jks new file mode 100644 index 0000000..6bc6d1f Binary files /dev/null and b/assets/certs/externalApp.jks differ diff --git a/assets/certs/externalApp.key.pem b/assets/certs/externalApp.key.pem new file mode 100644 index 0000000..fcf7af3 --- /dev/null +++ b/assets/certs/externalApp.key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCQUWu4poVsHkKN +KldUyJqnAl9kcCIWCHqFbTysbcJI4HG+lo/Yh7Y98G3xsxqDB/dh+E1x1Y4CLpEi +clB+UY2jLtX9GXfRHqWQhi6+ONzUScMI3+R0gmrogpO3Tg3twMw1oqJTaDzQ2rne +gAfnRip9EoZM76RtjIsAGa1A2Yo7E2LrHEZofXxzL4FWJEnseesU3F3QkLhdG372 +dcwcHysLGP492enSUXvuWqgpNnJWzY6CKpBzY1TmSSlvmJovpjfkoypAyHFtPG+r +Q90YQhZLk0ev0Dspqvhsv9oS1CBWWQC1OCeLN1eqCFJwYtxjEdoTey53dOBQ8VEe +AO2dNItFAgMBAAECggEAAmrWuNRTOk0kdLxfk5w7mO4Nfn9xVrikIr2CbWn2PeXC +ifx4ItqdFxsCoHCNUmINBv9TfsNiuk8g37iV+BOyIWhcrb1iOCbBA7N3r3iA3G5y +3aBwcXIoy8W6JzEfwxp+YSyc9vQxRpdPUzaGS12twwQPK1U9Rhd7UZBcilBKhDRH +vF5ZB3tONeheYX46tl8Z6kRMxCzigyvQY4qXngSYinHYzaqyw+Wume0EsgMRxIBP +j7ad8LNM7ppEitrnJ2z5+qccHddVPTT8F9sP4yq6IjeVHqjlw7bi/cnKCsGewiKC +x4UqzX+ZLbTCAOxD332nIQFPlBLr6PvOU3cb+pfsYQKBgQDEF9XmI+i3IFjVAbSA +OFBIqNK9V4V8/qU2Xy1Gak4gKezjj5E3o57VJWRbeCfhJA4cWorLvI/XAtZLFVSD +66fMRSBoj4J0FHeVz9kVI7umUknmgayG23ey1hQkBzrIagfpaL6OJdCjNAsudLSb +FYThstbue1hxVSxkQbH/oi/RJQKBgQC8aFTM3UB7HWqS8VuCb7PMqauFbUpFF5vB +1SUnoRe/fKEOfiB78K2FeE3H/ccVSr/l0Ye2aimSUQIUmi07F/IzCnj1IB2Rev9u +j+GKvnQPjouW4JhS+ZH2jMCfWwaJtgizeuUlzgQxchj1pmHA3UG74ei79bKt2qmC +g7StkaIHoQKBgQCbT5Gf9QMFv/37v5z6DSAxXF2Fj8Nvi7TJCrsuUVZNjUdNuVE4 +M0TC5xnEhLd5T3hJpsDVuyRmFJ4r29oTnltJo9qWVkvpqqhIpNX4M1QV2Iklo8FF +EqCMqZhMLNm3EJvxl3+N0I+eI8NTaSX+yx1zMZWgT1tucBp30bysjwW2bQKBgFXm +W4Nr/NIk/0ovsMEvnJJbaVBUG+CUevdM7ru6vtEXSXcKGlVnzjVkPFJKalJS2ls1 +xOJuVLXZKVGrWaPvrwWGaM+Z7OE/auZFw1c2rkPJgeswS0LJdrsqQUhmf/yZei4a +gg9Sdqb0llyplzgPqMC4pxvLUcPiRhazZdUc6PsBAoGAcFFoKWPhLLaqGyotnsRy +hlRP7oDA1/isYlAM98SYtD+h5/54NFs4Uk2hfAJNDzioxOiChud3VHx5FaVwXmeY +dWNKIa/YroH35nv4rwNIaDNiWm9K5aBrQIx8oJJbUPlCOkWk/kKui0ZsuNwSAG35 +ByyI0oYSpvirNMathReJ5ss= +-----END PRIVATE KEY----- diff --git a/assets/certs/externalApp.p12 b/assets/certs/externalApp.p12 new file mode 100644 index 0000000..3871d12 Binary files /dev/null and b/assets/certs/externalApp.p12 differ diff --git a/src/main/java/acq/acq/src/Main.java b/src/main/java/acq/acq/src/Main.java index 626968a..cb11032 100644 --- a/src/main/java/acq/acq/src/Main.java +++ b/src/main/java/acq/acq/src/Main.java @@ -1,7 +1,50 @@ package acq.acq.src; +// File: AcqClient.java +import javax.net.ssl.*; +import java.io.*; +import java.security.KeyStore; public class Main { - public static void main(String[] args) { - + public static void main(String[] args) throws Exception { + String host = "localhost"; + int port = 8443; + + // If client needs to present cert (mTLS) + String keystorePath = "assets/certs/acq.p12"; + char[] keystorePass = "hepl".toCharArray(); + + // Truststore to trust the server's CA + String truststorePath = "assets/certs/acq-trust.jks"; + char[] truststorePass = "heplhepl".toCharArray(); + + KeyStore ks = KeyStore.getInstance("PKCS12"); + try (FileInputStream fis = new FileInputStream(keystorePath)) { + ks.load(fis, keystorePass); + } + KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); + kmf.init(ks, keystorePass); + + KeyStore ts = KeyStore.getInstance("JKS"); + try (FileInputStream fis = new FileInputStream(truststorePath)) { + ts.load(fis, truststorePass); + } + TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); + tmf.init(ts); + + SSLContext ctx = SSLContext.getInstance("TLS"); + ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + + SSLSocketFactory factory = ctx.getSocketFactory(); + try (SSLSocket socket = (SSLSocket) factory.createSocket(host, port)) { + socket.startHandshake(); + BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); + BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); + + out.write("Hello ACS\n"); + out.flush(); + + String resp = in.readLine(); + System.out.println("Response from ACS: " + resp); + } } } diff --git a/src/main/java/acs/acs/src/Main.java b/src/main/java/acs/acs/src/Main.java index b72340c..649bce0 100644 --- a/src/main/java/acs/acs/src/Main.java +++ b/src/main/java/acs/acs/src/Main.java @@ -1,7 +1,57 @@ package acs.acs.src; +// File: AcsServer.java +import javax.net.ssl.*; +import java.io.*; +import java.security.KeyStore; + public class Main { - public static void main(String[] args) { - + public static void main(String[] args) throws Exception { + int port = 8443; + // Keystore containing server private key + cert (PKCS12 or JKS) + String keystorePath = "assets/certs/acs.p12"; + char[] keystorePass = "hepl".toCharArray(); + + // Truststore (to verify client if mutual TLS) + String truststorePath = "assets/certs/acs-trust.jks"; + char[] truststorePass = "heplhepl".toCharArray(); + + KeyStore ks = KeyStore.getInstance("PKCS12"); + try (FileInputStream fis = new FileInputStream(keystorePath)) { + ks.load(fis, keystorePass); + } + KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); + kmf.init(ks, keystorePass); + + KeyStore ts = KeyStore.getInstance("JKS"); + try (FileInputStream fis = new FileInputStream(truststorePath)) { + ts.load(fis, truststorePass); + } + TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); + tmf.init(ts); + + SSLContext ctx = SSLContext.getInstance("TLS"); + ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + + SSLServerSocketFactory ssf = ctx.getServerSocketFactory(); + SSLServerSocket serverSocket = (SSLServerSocket) ssf.createServerSocket(port); + // si vous voulez mTLS : + serverSocket.setNeedClientAuth(true); + + System.out.println("ACS listening on port " + port); + while (true) { + try (SSLSocket socket = (SSLSocket) serverSocket.accept()) { + BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); + BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); + + String line = in.readLine(); // simple single-line message + System.out.println("Received from ACQ: " + line); + + out.write("ACK from ACS\n"); + out.flush(); + } catch (IOException e) { + e.printStackTrace(); + } + } } } diff --git a/src/main/java/common/common/src/ports/Ports.java b/src/main/java/common/common/src/ports/Ports.java new file mode 100644 index 0000000..896e47f --- /dev/null +++ b/src/main/java/common/common/src/ports/Ports.java @@ -0,0 +1,9 @@ +package common.common.src.ports; + +public class Ports { + /** + * Port d'écoute du service ACS pour la communication avec l'application externe. + */ + public static int PORT_AUTH = 8786; + public static String ACS_HOST = "127.0.0.1"; +} diff --git a/src/main/java/externalApp/externalApp/src/Main.java b/src/main/java/externalApp/externalApp/src/Main.java index 749d097..aa907b7 100644 --- a/src/main/java/externalApp/externalApp/src/Main.java +++ b/src/main/java/externalApp/externalApp/src/Main.java @@ -1,9 +1,75 @@ package externalApp.externalApp.src; +import common.common.src.ports.Ports; import common.common.src.logger.Logger; +import org.gradle.internal.impldep.com.fasterxml.jackson.databind.ObjectMapper; +import org.gradle.internal.impldep.com.fasterxml.jackson.databind.node.ObjectNode; + +import javax.net.ssl.HttpsURLConnection; +import java.io.*; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.security.*; +import java.security.cert.CertificateException; +import java.util.Base64; public class Main { - public static void main(String[] args) { - Logger.displayInfo("Hello World"); + public static void main(String[] args) throws IOException, KeyStoreException, UnrecoverableKeyException, NoSuchAlgorithmException, InvalidKeyException, SignatureException, URISyntaxException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + System.out.println("Quel est la date d'expiration de la carte de crédit ? (MM/AA)"); + String expirationDate = br.readLine(); + Logger.displayInfo("Date d'expiration saisie : " + expirationDate); + System.out.println("Numéro de la carte de crédit : "); + String cardNumber = br.readLine(); + Logger.displayInfo("Numéro de carte saisi : " + cardNumber); + + // Construction du JSON + ObjectMapper mapper = new ObjectMapper(); + ObjectNode json = mapper.createObjectNode(); + json.put("expirationDate", expirationDate); + json.put("cardNumber", cardNumber); + String jsonString = mapper.writeValueAsString(json); + + // Signer le JSON + KeyStore keyStore = KeyStore.getInstance("PKCS12"); + char[] password = /* TODO */.toCharArray(); + try (FileInputStream pkFile = new FileInputStream("ma_cle.p12")) { + keyStore.load(pkFile, password); + } catch (CertificateException | NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + PrivateKey privateKey = (PrivateKey) keyStore.getKey(/* TODO */, password); + Signature signature = Signature.getInstance("SHA256withRSA"); + signature.initSign(privateKey); + signature.update(jsonString.getBytes(StandardCharsets.UTF_8)); + byte[] signedBytes = signature.sign(); + + String signatureBase64 = Base64.getEncoder().encodeToString(signedBytes); + + // Construction du JSON final avec la signature + ObjectNode finalJson = mapper.createObjectNode(); + finalJson.put("data", jsonString); + finalJson.put("signature", signatureBase64); + + String finalPayload = mapper.writeValueAsString(finalJson); + + // Envoi à l'ACS + Logger.displayInfo("Envoi des informations au service d'authentification sur le port " + Ports.PORT_AUTH + " à l'hôte " + Ports.ACS_HOST); + URL url = new URI("https://" + Ports.ACS_HOST + ":" + Ports.PORT_AUTH).toURL(); + HttpsURLConnection con = (HttpsURLConnection) url.openConnection(); + + con.setRequestMethod("POST"); + con.setRequestProperty("Content-Type", "application/json"); + con.setDoOutput(true); + + try (OutputStream os = con.getOutputStream()) { + os.write(finalPayload.getBytes(StandardCharsets.UTF_8)); + Logger.displaySent("Payload final envoyé : " + finalPayload); + } + + int responseCode = con.getResponseCode(); + Logger.displayReceived("Code de réponse reçu : " + responseCode); } }