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);
+ }
+
+}