From 155dae2540930fedf4388959a6e11998131cadc3 Mon Sep 17 00:00:00 2001 From: Francesco Mancuso Date: Wed, 25 Mar 2026 22:18:43 +0100 Subject: [PATCH] [1.0.0] Upload first version --- .gitignore | 2 + cryptea/pom.xml | 43 +++ .../main/java/tools/cryptea/Certificate.java | 313 ++++++++++++++++++ .../src/main/java/tools/cryptea/Digest.java | 50 +++ cryptea/src/main/java/tools/cryptea/Keys.java | 126 +++++++ cryptea/src/main/java/tools/cryptea/RSA.java | 100 ++++++ .../tools/cryptea/utils/Base64Helper.java | 92 +++++ .../main/java/tools/cryptea/utils/EspMod.java | 55 +++ .../java/tools/cryptea/utils/HexHelper.java | 42 +++ .../java/tools/cryptea/utils/JsonHelper.java | 76 +++++ 10 files changed, 899 insertions(+) create mode 100644 cryptea/pom.xml create mode 100644 cryptea/src/main/java/tools/cryptea/Certificate.java create mode 100644 cryptea/src/main/java/tools/cryptea/Digest.java create mode 100644 cryptea/src/main/java/tools/cryptea/Keys.java create mode 100644 cryptea/src/main/java/tools/cryptea/RSA.java create mode 100644 cryptea/src/main/java/tools/cryptea/utils/Base64Helper.java create mode 100644 cryptea/src/main/java/tools/cryptea/utils/EspMod.java create mode 100644 cryptea/src/main/java/tools/cryptea/utils/HexHelper.java create mode 100644 cryptea/src/main/java/tools/cryptea/utils/JsonHelper.java diff --git a/.gitignore b/.gitignore index a7e4258..ba07665 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,5 @@ buildNumber.properties # JDT-specific (Eclipse Java Development Tools) .classpath +# vscode +.vscode/ \ No newline at end of file diff --git a/cryptea/pom.xml b/cryptea/pom.xml new file mode 100644 index 0000000..30a1639 --- /dev/null +++ b/cryptea/pom.xml @@ -0,0 +1,43 @@ + + + 4.0.0 + + tools.cryptea + cryptea-tools + 1.0.0 + jar + + Cryptea Tools + Libreria open source per integrare Cryptea nel tuo workflow. Maggiori dettagli qui https://cryptea.web.francescomancuso.it + + + 25 + 25 + UTF-8 + + + + + tools.jackson.core + jackson-databind + 3.0.3 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.13.0 + + ${maven.compiler.source} + ${maven.compiler.target} + + + + + + \ No newline at end of file diff --git a/cryptea/src/main/java/tools/cryptea/Certificate.java b/cryptea/src/main/java/tools/cryptea/Certificate.java new file mode 100644 index 0000000..c4c7de5 --- /dev/null +++ b/cryptea/src/main/java/tools/cryptea/Certificate.java @@ -0,0 +1,313 @@ +/** + * @fileoverview Libreria Cryptea - Gestione dei certificati e verifica + * + * @author Francesco Mancuso + * @version 1.0 + * @since 2026-03 + * + * Copyright © 2026 Francesco Mancuso - www.francescomancuso.it + * Tutti i diritti riservati. + * + * Questo software è protetto dalle leggi sul diritto d'autore. + * + * È vietato l'uso, la copia, la modifica, la distribuzione o + * la creazione di opere derivate senza autorizzazione scritta + * esplicita dell'autore. + */ + +package tools.cryptea; + +import java.math.BigInteger; +import java.net.ConnectException; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.net.http.HttpResponse.BodyHandlers; +import java.net.http.HttpTimeoutException; +import java.time.Duration; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; + +import tools.cryptea.utils.Base64Helper; +import tools.cryptea.utils.HexHelper; +import tools.cryptea.utils.JsonHelper; +import tools.jackson.databind.JsonNode; +import tools.jackson.databind.ObjectMapper; +import tools.jackson.databind.node.ObjectNode; + +public class Certificate { + + // Url base per verifica + public static final String BASE_URL = "https://cryptea.web.francescomancuso.it"; + + // per Jackson v3 + private static final ObjectMapper mapper = new ObjectMapper(); + + // per richieste HTTP + private static final HttpClient CLIENT = HttpClient.newBuilder() + .connectTimeout(Duration.ofSeconds(10)) + .version(HttpClient.Version.HTTP_1_1) + .build(); + + /** + * Verifica la validità di un certificato offline + * + * @param content Il certificato in formato CRYPTEA + * @return Un array, r[0] indica true/false, r[1] l'eventuale motivo di errore + * @throws Exception Nella gestione dei metadata e delle date + */ + public static String[] verify(String content) throws Exception { + String[] ret = new String[2]; + String publicKey = "-----BEGIN CRYPTEA PUBLIC KEY-----\r\n" + // + "AQAB.AMAh44IisBLbYPRAfer5SUp91wCl+9WuLsnRQ56HcXG//OKaMNSfv3mzCBu\r\n" + // + "oFgcY3tvVcAqFk6pFrxFq5r0EbG95wEbWP9GuU5y1l07c3dc7Jc2gc2ymCBM+4bL\r\n" + // + "Ine70GqRP6cM5XZuab7OGuFHQXWRI28wyo2obiSgCCkAMCFaHsK7vDMbUS9FRQYM\r\n" + // + "JS0/Xbp8RyQiSNaPyXUoNjEt9Mvqjqu+dpWuqfHe4myhtjSDLDlNN7oyg8OTfGpC\r\n" + // + "Oe4b0G48q5OxZoMEpcohwCkIDep0BtqNt1OJqAY/Md334lKAxlJGCMR0rxp3mD7k\r\n" + // + "5h5+fC8pFFjGanHyFsDj+tQDMrBs=\r\n" + // + "-----END CRYPTEA PUBLIC KEY-----"; + String cleaned = content + .replace("-----BEGIN CRYPTEA CERTIFICATE-----", "") + .replace("-----END CRYPTEA CERTIFICATE-----", "") + .replaceAll("\\s", ""); + cleaned = cleaned.trim(); + if (cleaned.contains("CRYPTEA") || cleaned.contains("CERTIFICATE")) { + throw new IllegalArgumentException("Formato certificato non corretto!"); + } + String[] parts = cleaned.split("\\."); + if (parts.length < 4) + throw new Exception("Formato certificato incompleto"); + String metadata = Base64Helper.toString(parts[0]); + BigInteger signature = Base64Helper.toBigInteger(parts[3]); + + // 1. Prima di tutto, verifichiamo la firma + + // 1.a Decodifico la firma ottenuta + BigInteger[] kPubCA = Keys.publicFromFile("cryptea", publicKey); + // kPub[0] = e + // kPub[1] = n + BigInteger decrypted = RSA.decryptWithPublic(signature, kPubCA[0], kPubCA[1]); + + // 1.b Costruisco il payload + String toBeSigned = parts[0] + "." + parts[1] + "." + parts[2]; + + // 1.c Calcolo il digest + byte[] hash = Digest.getByteDigest(toBeSigned.getBytes()); + + // 1.d Confronto digest con quello ottenuto + // Forzatura del segno per evitare errori + BigInteger calculated = new BigInteger(1, hash); + + if (calculated.equals(decrypted)) { + // Firma valida! Controllo i metadata + String[] metadataH = metadata.split("\\|"); + if (metadataH.length < 6) { + // Formato metadata incompleto, non valido! + throw new Exception("Formato dell'intestazione non valido!"); + } + + // Verifica rapida sull'owner + if (!metadataH[0].contains("owner=")) { + // Manca la dichiarazione owner! + throw new Exception("Formato dell'intestazione non valido!"); + } + + if (!metadataH[1].contains("id=")) { + // Manca la dichiarazione id! + throw new Exception("Formato dell'intestazione non valido!"); + } + + // Verifica issuer + if (!metadataH[2].equals("issuer=CrypteaCA")) { + // Issuer non valido! + throw new Exception("Formato dell'intestazione non valido!"); + } + + // Verifica sulla versione + if (!metadataH[3].equals("version=1.0")) { + // Versione non valida! + throw new Exception("Formato dell'intestazione non valido!"); + } + + // Verifica sulla data di creazione e scadenza + try { + // Rimuovo i prefissi prima di fare il parsing delle date + String strCreated = metadataH[4].replace("created=", ""); + String strExpiry = metadataH[5].replace("expiry=", ""); + + OffsetDateTime created = OffsetDateTime.parse(strCreated); + OffsetDateTime expiry = OffsetDateTime.parse(strExpiry); + + if (created == null || expiry == null) { + // Devono essere date valide + throw new Exception("Errore nel parsing della data, formato errato!"); + } + + // Confronto in UTC + OffsetDateTime now = OffsetDateTime.now(ZoneOffset.UTC); + + if (expiry.isAfter(created) && expiry.isAfter(now)) { + // Ok, valido! + ret[0] = "true"; + ret[1] = ""; + return ret; + } else { + // La data di scadenza deve essere sempre dopo la creazione e "now" + ret[0] = "false"; + ret[1] = "Il certificato è scaduto!"; + return ret; + } + + } catch (Exception e) { + // Errore formato date + throw new Exception("Errore nel parsing della data, formato errato!"); + } + + } else { + // Firma non valida, esco... + ret[0] = "false"; + ret[1] = "La firma non è valida. Il contenuto è stato alterato!"; + return ret; + } + + } + + /** + * Estrae i metadata (se validi) da un certificato + * + * @param content Il certificato in formato CRYPTEA + * @return I metadati in formato String[] + * @throws Exception Se si verificano problemi nel formato + */ + public static String[] extractMetadata(String content) throws Exception { + String cleaned = content + .replace("-----BEGIN CRYPTEA CERTIFICATE-----", "") + .replace("-----END CRYPTEA CERTIFICATE-----", "") + .replaceAll("\\s", ""); + + cleaned = cleaned.trim(); + if (cleaned.contains("CRYPTEA") || cleaned.contains("CERTIFICATE")) { + throw new IllegalArgumentException("Formato certificato non corretto!"); + } + String[] parts = cleaned.split("\\."); + if (parts.length < 4) + throw new Exception("Formato certificato incompleto"); + return Base64Helper.toString(parts[0]).split("\\|"); + } + + /** + * Estrae la firma digitale (fingerprint) del certificato + * @param content Il certificato in formato CRYPTEA + * @return Una stringa, la firma in formato HEX + * @throws Exception Nella gestione del formato del certificato + */ + public static String extractSignature(String content) throws Exception { + String cleaned = content + .replace("-----BEGIN CRYPTEA CERTIFICATE-----", "") + .replace("-----END CRYPTEA CERTIFICATE-----", "") + .replaceAll("\\s", ""); + cleaned = cleaned.trim(); + if (cleaned.contains("CRYPTEA") || cleaned.contains("CERTIFICATE")) { + throw new IllegalArgumentException("Formato certificato non corretto!"); + } + String[] parts = cleaned.split("\\."); + if (parts.length < 4) + throw new Exception("Formato certificato incompleto"); + return HexHelper.fromBigInteger(new BigInteger(1, Base64Helper.toBytes(parts[3]))); + } + + /** + * Controlla se il certificato è stato revocato, attraverso una verifica remota + * OCSP (Online Certificate Status Protocol) + * + * @param mdex I metadati estratti dal certificato + * @return Un array, r[0] indica true/false, r[1] l'eventuale motivo di errore + * @throws Exception Nella gestione della richiesta HTTP + */ + public static String[] certificateIsActive(String[] metadataExtracted) throws Exception { + String[] ret = new String[2]; + + ObjectNode json = mapper.createObjectNode(); + json.put("action", "verify_cert"); + + ObjectNode metadata = mapper.createObjectNode(); + String finalJson = null; + + try { + for (String meta : metadataExtracted) { + // Split del "=" + String[] data = meta.split("\\="); + metadata.put(data[0], data[1]); + } + + json.set("metadata", metadata); + finalJson = JsonHelper.nodeToJson(json); + } catch (Exception e) { + throw new Exception("Formato metadati errato."); + } + + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI(BASE_URL + "/api/v2/verify")) + .headers("Content-Type", "application/json") + .timeout(Duration.ofSeconds(15)) + .POST(HttpRequest.BodyPublishers.ofString(finalJson)) + .build(); + + try { + HttpResponse response = CLIENT.send(request, BodyHandlers.ofString()); + + JsonNode jsonRes = JsonHelper.jsonToNode(response.body()); + String status = jsonRes.get("status").asString(); + + if (status.equals("ok")) { + ret[0] = jsonRes.get("isActive").asString(); + } else { + ret[0] = "null"; + ret[1] = "Errore nel processo di verifica!"; + } + + } catch (HttpTimeoutException e) { + throw new HttpTimeoutException("Timeout del server. Potrebbe essere offline?"); + } catch (Exception e) { + throw e; + } + + return ret; + } + + /** + * Effettua il ping al server CrypteaCA per verificare lo stato dei servizi + * @return TRUE/FALSE + * @throws HttpTimeoutException Nella gestione della richiesta + */ + public static boolean ping() throws HttpTimeoutException { + try { + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI(BASE_URL + "/api/v2/ping")) + .headers("Content-Type", "application/json") + .timeout(Duration.ofSeconds(15)) + .GET() + .build(); + + HttpResponse response = CLIENT.send(request, BodyHandlers.ofString()); + + JsonNode jsonRes = JsonHelper.jsonToNode(response.body()); + String status = jsonRes.get("status").asString(); + + if (status.equals("ok")) { + return true; + } else { + return false; + } + + } catch (HttpTimeoutException e) { + throw new HttpTimeoutException("Timeout del server. Potrebbe essere offline?"); + } catch (ConnectException e) { + return false; + } catch (Exception e) { + throw new HttpTimeoutException("Errore nel contattare il server. Stato sconosciuto."); + } + } + +} diff --git a/cryptea/src/main/java/tools/cryptea/Digest.java b/cryptea/src/main/java/tools/cryptea/Digest.java new file mode 100644 index 0000000..c2ffcac --- /dev/null +++ b/cryptea/src/main/java/tools/cryptea/Digest.java @@ -0,0 +1,50 @@ +/** + * @fileoverview Libreria Cryptea - Calcolo del digest SHA-512 + * + * @author Francesco Mancuso + * @version 1.0 + * @since 2026-03 + * + * Copyright © 2026 Francesco Mancuso - www.francescomancuso.it + * Tutti i diritti riservati. + * + * Questo software è protetto dalle leggi sul diritto d'autore. + * + * È vietato l'uso, la copia, la modifica, la distribuzione o + * la creazione di opere derivate senza autorizzazione scritta + * esplicita dell'autore. + */ + +package tools.cryptea; + +import java.math.BigInteger; +import java.security.MessageDigest; + +public class Digest { + + /** + * Calcola il digest generando una stringa HEX + * @param bytes Array di byte come input del digest + * @return Il digest in formato String HEX + * @throws Exception + */ + public static String getStringDigest(byte[] bytes) throws Exception { + MessageDigest digest = MessageDigest.getInstance("SHA-512"); + byte[] hash = digest.digest(bytes); + String hashtext = new BigInteger(1, hash).toString(16).toUpperCase(); + return hashtext; + } + + /** + * Calcola il digest generando un array di byte[] + * @param bytes Array di byte come input del digest + * @return Il digest in formato byte[] + * @throws Exception + */ + public static byte[] getByteDigest(byte[] bytes) throws Exception { + MessageDigest digest = MessageDigest.getInstance("SHA-512"); + byte[] hash = digest.digest(bytes); + return hash; + } + +} diff --git a/cryptea/src/main/java/tools/cryptea/Keys.java b/cryptea/src/main/java/tools/cryptea/Keys.java new file mode 100644 index 0000000..da669d5 --- /dev/null +++ b/cryptea/src/main/java/tools/cryptea/Keys.java @@ -0,0 +1,126 @@ +/** + * @fileoverview Libreria Cryptea - Gestione delle chiavi nel formato Cryptea + * + * @author Francesco Mancuso + * @version 1.0 + * @since 2026-03 + * + * Copyright © 2026 Francesco Mancuso - www.francescomancuso.it + * Tutti i diritti riservati. + * + * Questo software è protetto dalle leggi sul diritto d'autore. + * + * È vietato l'uso, la copia, la modifica, la distribuzione o + * la creazione di opere derivate senza autorizzazione scritta + * esplicita dell'autore. + */ + +package tools.cryptea; + +import java.math.BigInteger; +import tools.cryptea.utils.Base64Helper; + +public class Keys { + + /** + * Funzione Helper per stampare le chiavi su righe da 64 caratteri + * @param input Il contenuto del file + * @return Il contenuto formattato + */ + private static String wrapLines(String input) { + StringBuilder res = new StringBuilder(); + char[] array = input.toCharArray(); + int cont = 0; + for (int i = 0; i < input.length(); i++) { + res.append(array[i]); + cont++; + // Arrivo a 64, ma evito l'ultimo char + if (cont == 64 && i < input.length() - 1) { + res.append("\n"); + cont = 0; + } + } + return res.toString(); + } + + /** + * Genera il contenuto del file che contiene Kpub + * + * @param n Modulo n di RSA + * @param e Esponente pubblico di RSA + * @return Ritorna la chiave di tipo String + */ + public static String publicToFile(BigInteger e, BigInteger n) { + String b64E = Base64Helper.fromBigInteger(e); + String b64N = Base64Helper.fromBigInteger(n); + String crypteaF = b64E + "." + b64N; + return "-----BEGIN CRYPTEA PUBLIC KEY-----\n" + wrapLines(crypteaF) + "\n-----END CRYPTEA PUBLIC KEY-----"; + } + + /** + * Legge il contenuto di un file che contiene Kpub + * + * @param content Il contenuto formattato + * @return Ritorna i valori "e" "n" in formato BigInteger[] + */ + public static BigInteger[] publicFromFile(String type, String content) throws Exception { + BigInteger[] kPub = { BigInteger.ZERO, BigInteger.ZERO }; + String cleaned = content + .replace("-----BEGIN CRYPTEA PUBLIC KEY-----", "") + .replace("-----END CRYPTEA PUBLIC KEY-----", "") + .replaceAll("\\s", "") + .trim(); + if (cleaned.contains("CRYPTEA") || cleaned.contains("KEY")) { + throw new IllegalArgumentException("Formato chiave non corretto!"); + } + String[] parts = cleaned.split("\\."); + if (parts.length < 2) + throw new Exception("Formato chiave non valido"); + kPub[0] = Base64Helper.toBigInteger(parts[0]); // e + kPub[1] = Base64Helper.toBigInteger(parts[1]); // n + return kPub; + } + + /** + * Genera il contenuto del file che contiene Kpr + * + * @param k Esponente privato di RSA + * @param n Modulo n di RSA + * @param p Numero primo p + * @param q Numero primo q + * @return Ritorna la chiave di tipo String + */ + public static String privateToFile(BigInteger k, BigInteger n, BigInteger p, BigInteger q) { + String b64K = Base64Helper.fromBigInteger(k); + String b64N = Base64Helper.fromBigInteger(n); + String b64P = Base64Helper.fromBigInteger(p); + String b64Q = Base64Helper.fromBigInteger(q); + String crypteaF = b64K + "." + b64N + "." + b64P + "." + b64Q; + return "-----BEGIN CRYPTEA PRIVATE KEY-----\n" + wrapLines(crypteaF) + "\n-----END CRYPTEA PRIVATE KEY-----"; + } + + /** + * Legge il contenuto di un file che contiene Kpr + * + * @param content Il contenuto formattato + * @return Ritorna i valori "k" "n" in formato BigInteger[] + */ + public static BigInteger[] privateFromFile(String content) throws Exception { + BigInteger[] kPr = { BigInteger.ZERO, BigInteger.ZERO }; + String cleaned = content + .replace("-----BEGIN CRYPTEA PRIVATE KEY-----", "") + .replace("-----END CRYPTEA PRIVATE KEY-----", "") + .replaceAll("\\s", "") + .trim(); + if (cleaned.contains("CRYPTEA") || cleaned.contains("KEY")) { + throw new IllegalArgumentException("Formato chiave non corretto!"); + } + String[] parts = cleaned.split("\\."); + if (parts.length < 4) + throw new Exception("Formato chiave privata incompleto"); + kPr[0] = Base64Helper.toBigInteger(parts[0]); + kPr[1] = Base64Helper.toBigInteger(parts[1]); + return kPr; + } + +} diff --git a/cryptea/src/main/java/tools/cryptea/RSA.java b/cryptea/src/main/java/tools/cryptea/RSA.java new file mode 100644 index 0000000..f13042f --- /dev/null +++ b/cryptea/src/main/java/tools/cryptea/RSA.java @@ -0,0 +1,100 @@ +/** + * @fileoverview Libreria Cryptea - Operazioni RSA cifratura / decifratura + * + * @author Francesco Mancuso + * @version 1.0 + * @since 2026-03 + * + * Copyright © 2026 Francesco Mancuso - www.francescomancuso.it + * Tutti i diritti riservati. + * + * Questo software è protetto dalle leggi sul diritto d'autore. + * + * È vietato l'uso, la copia, la modifica, la distribuzione o + * la creazione di opere derivate senza autorizzazione scritta + * esplicita dell'autore. + */ + +package tools.cryptea; + +import java.math.BigInteger; +import tools.cryptea.utils.EspMod; + +public class RSA { + + /** + * Cifra il contenuto con la chiave pubblica + * @param input in formato BigInt + * @param e Esponente pubblico RSA + * @param n Modulo RSA + * @return Risultato dell'operazione + */ + public static BigInteger encryptWithPublic(BigInteger input, BigInteger e, BigInteger n) { + BigInteger output = BigInteger.ZERO; + + if (n != null && e != null) { + output = EspMod.doIt(input, e, n); + } else { + throw new IllegalArgumentException("Parametri chiave pubblica incompleti o non validi."); + } + + return output; + } + + /** + * Cifra il contenuto con la chiave privata + * @param input in formato BigInt + * @param k Esponente privato RSA + * @param n Modulo RSA + * @return Risultato dell'operazione + */ + public static BigInteger encryptWithPrivate(BigInteger input, BigInteger k, BigInteger n) { + BigInteger output = BigInteger.ZERO; + + if (n != null && k != null) { + output = EspMod.doIt(input, k, n); + } else { + throw new IllegalArgumentException("Parametri chiave privata incompleti o non validi."); + } + + return output; + } + + /** + * Decifra il contenuto con la chiave privata + * @param input in formato BigInt + * @param k Esponente privato RSA + * @param n Modulo RSA + * @return Risultato dell'operazione + */ + public static BigInteger decryptWithPrivate(BigInteger input, BigInteger k, BigInteger n) { + BigInteger output = BigInteger.ZERO; + + if (n != null && k != null) { + output = EspMod.doIt(input, k, n); + } else { + throw new IllegalArgumentException("Parametri chiave privata incompleti o non validi."); + } + + return output; + } + + /** + * Decifra il contenuto con la chiave pubblica + * @param input in formato BigInt + * @param e Esponente pubblico RSA + * @param n Modulo RSA + * @return Risultato dell'operazione + */ + public static BigInteger decryptWithPublic(BigInteger input, BigInteger e, BigInteger n) { + BigInteger output = BigInteger.ZERO; + + if (n != null && e != null) { + output = EspMod.doIt(input, e, n); + } else { + throw new IllegalArgumentException("Parametri chiave pubblica incompleti o non validi."); + } + + return output; + } +} \ No newline at end of file diff --git a/cryptea/src/main/java/tools/cryptea/utils/Base64Helper.java b/cryptea/src/main/java/tools/cryptea/utils/Base64Helper.java new file mode 100644 index 0000000..aa1d4cc --- /dev/null +++ b/cryptea/src/main/java/tools/cryptea/utils/Base64Helper.java @@ -0,0 +1,92 @@ +/** + * @fileoverview Libreria Cryptea - Strumenti di conversione Base64 + * + * @author Francesco Mancuso + * @version 1.0 + * @since 2026-03 + * + * Copyright © 2026 Francesco Mancuso - www.francescomancuso.it + * Tutti i diritti riservati. + * + * Questo software è protetto dalle leggi sul diritto d'autore. + * + * È vietato l'uso, la copia, la modifica, la distribuzione o + * la creazione di opere derivate senza autorizzazione scritta + * esplicita dell'autore. + */ + +package tools.cryptea.utils; + +import java.math.BigInteger; +import java.nio.charset.StandardCharsets; +import java.util.Base64; + +public class Base64Helper { + + /** + * Trasforma un numero BigInteger in una stringa Base64 + * + * @param n + * @return String + */ + public static String fromBigInteger(BigInteger n) { + return Base64.getEncoder().encodeToString(n.toByteArray()); + } + + /** + * Trasforma una stringa Base64 in un numero BigInteger + * + * @param base64 + * @return BigInteger + */ + public static BigInteger toBigInteger(String base64) { + // da base64 salvo i bytes + byte[] bytes = Base64.getDecoder().decode(base64); + + // uso 1 per forzare il segno positivo ed evitare errori + return new BigInteger(1, bytes); + } + + /** + * Trasforma un array di bytes in una stringa Base64 + * + * @param bytes + * @return String + */ + public static String fromBytes(byte[] bytes) { + return Base64.getEncoder().encodeToString(bytes); + } + + /** + * Trasforma una stringa Base64 in un array di bytes + * + * @param base64 + * @return byte[] + */ + public static byte[] toBytes(String base64) { + // da base64 salvo i bytes + byte[] bytes = Base64.getDecoder().decode(base64); + + // uso 1 per forzare il segno positivo ed evitare errori + return bytes; + } + + /** + * Trasforma un oggetto String in stringa Base64 + * @param content + * @return + */ + public static String fromString(String content) { + return fromBytes(content.getBytes()); + } + + /** + * Trasforma una stringa Base64 in un oggetto String + * @param content + * @return + */ + public static String toString(String content) { + return new String(Base64.getDecoder().decode(content), StandardCharsets.UTF_8); + } + +} diff --git a/cryptea/src/main/java/tools/cryptea/utils/EspMod.java b/cryptea/src/main/java/tools/cryptea/utils/EspMod.java new file mode 100644 index 0000000..112af58 --- /dev/null +++ b/cryptea/src/main/java/tools/cryptea/utils/EspMod.java @@ -0,0 +1,55 @@ +/** + * @fileoverview Libreria Cryptea - Algoritmo di Esponenziazione Modulare + * + * @author Francesco Mancuso + * @version 1.0 + * @since 2026-03 + * + * Copyright © 2026 Francesco Mancuso - www.francescomancuso.it + * Tutti i diritti riservati. + * + * Questo software è protetto dalle leggi sul diritto d'autore. + * + * È vietato l'uso, la copia, la modifica, la distribuzione o + * la creazione di opere derivate senza autorizzazione scritta + * esplicita dell'autore. + */ + +package tools.cryptea.utils; + +import java.math.BigInteger; + +public class EspMod { + + /** + * Algoritmo di Esponenziazione Modulare per velocizzare i calcoli RSA. + * Maggiori dettagli nella nostra documentazione https://cryptea.web.francescomancuso.it + * @param a Base della potenza + * @param b Esponente della potenza + * @param n Numero mod n + * @return Risultato operazione + */ + public static BigInteger doIt(BigInteger a, BigInteger b, BigInteger n) { + BigInteger result = BigInteger.valueOf(1); + + // 1. Calcolo il primo modulo della produttoria + a = a.mod(n); + + // 2. Avvio il ciclo while per effettuare tutti i prodotti + // mentre b > 0 (true = 1) + while (b.compareTo(BigInteger.ZERO) == 1) { + if (b.getLowestSetBit() == 0) { + // se è dispari (ultimo bit uguale a 1) + result = (result.multiply(a)).mod(n); + } + + // 3. Calcolo la successiva potenza + a = (a.multiply(a)).mod(n); + + // 4. Divido per 2 b + b = b.shiftRight(1); + } + + return result; + } +} diff --git a/cryptea/src/main/java/tools/cryptea/utils/HexHelper.java b/cryptea/src/main/java/tools/cryptea/utils/HexHelper.java new file mode 100644 index 0000000..be4ef55 --- /dev/null +++ b/cryptea/src/main/java/tools/cryptea/utils/HexHelper.java @@ -0,0 +1,42 @@ +/** + * @fileoverview Libreria Cryptea - Strumenti di conversione HEX + * + * @author Francesco Mancuso + * @version 1.0 + * @since 2026-03 + * + * Copyright © 2026 Francesco Mancuso - www.francescomancuso.it + * Tutti i diritti riservati. + * + * Questo software è protetto dalle leggi sul diritto d'autore. + * + * È vietato l'uso, la copia, la modifica, la distribuzione o + * la creazione di opere derivate senza autorizzazione scritta + * esplicita dell'autore. + */ + +package tools.cryptea.utils; + +import java.math.BigInteger; + +public class HexHelper { + + /** + * Trasforma un numero BigInteger in una stringa Hex + * @param n + * @return String + */ + public static String fromBigInteger(BigInteger n) { + return n.toString(16).toUpperCase(); + } + + /** + * Trasforma una stringa Hex in un numero BigInteger + * @param hex + * @return BigInteger + */ + public static BigInteger toBigInteger(String hex) { + return new BigInteger(hex, 16); + } + +} diff --git a/cryptea/src/main/java/tools/cryptea/utils/JsonHelper.java b/cryptea/src/main/java/tools/cryptea/utils/JsonHelper.java new file mode 100644 index 0000000..9d47ab1 --- /dev/null +++ b/cryptea/src/main/java/tools/cryptea/utils/JsonHelper.java @@ -0,0 +1,76 @@ +/** + * @fileoverview Libreria Cryptea - Strumenti di lavoro per JSON + * + * @author Francesco Mancuso + * @version 1.0 + * @since 2026-03 + * + * Copyright © 2026 Francesco Mancuso - www.francescomancuso.it + * Tutti i diritti riservati. + * + * Questo software è protetto dalle leggi sul diritto d'autore. + * + * È vietato l'uso, la copia, la modifica, la distribuzione o + * la creazione di opere derivate senza autorizzazione scritta + * esplicita dell'autore. + */ + +package tools.cryptea.utils; + +import tools.jackson.databind.JsonNode; +import tools.jackson.databind.ObjectMapper; +import tools.jackson.databind.node.ObjectNode; + +public class JsonHelper { + + // per Jackson v3 + private static final ObjectMapper mapper = new ObjectMapper(); + + /** + * Converte un Oggetto generico in formato JSON + * @param obj Oggetto generico da convertire + * @return + */ + public static String objectToJson(Object obj) { + try { + return mapper.writeValueAsString(obj); + } catch (Exception e) { + throw new RuntimeException("Errore durante la serializzazione JSON", e); + } + } + + /** + * Estrare un oggetto di tipo T da una stringa JSON + * @param Il tipo dell'oggetto da estrarre + * @param json Stringa JSON + * @param clazz La classe che rappresenta la struttura dell'oggetto + * @return + */ + public static T objectFromJson(String json, Class clazz) { + try { + return mapper.readValue(json, clazz); + } catch (Exception e) { + throw new RuntimeException("Errore durante la deserializzazione JSON", e); + } + } + + /** + * Converte un ObjectNode di Jackson in stringa JSON + * @param jsonNode Il nodo di partenza + * @return + */ + public static String nodeToJson(ObjectNode jsonNode) { + String result = mapper.writeValueAsString(jsonNode); + return result; + } + + /** + * Converte una stringa JSON in un ObjectNode di Jackson + * @param json La stringa JSON + * @return + */ + public static JsonNode jsonToNode(String json) { + return mapper.readTree(json); + } + +}