[1.0.0] New jar file and directory

This commit is contained in:
2026-03-25 22:29:09 +01:00
parent 97d68c953a
commit 43b410b1b9
11 changed files with 0 additions and 1 deletions

Binary file not shown.

43
source/pom.xml Normal file
View File

@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>tools.cryptea</groupId>
<artifactId>cryptea-tools</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<name>Cryptea Tools</name>
<description>Libreria open source per integrare Cryptea nel tuo workflow. Maggiori dettagli qui https://cryptea.web.francescomancuso.it</description>
<properties>
<maven.compiler.source>25</maven.compiler.source>
<maven.compiler.target>25</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>tools.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>3.0.3</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,313 @@
/**
* @fileoverview Libreria Cryptea - Gestione dei certificati e verifica
*
* @author Francesco Mancuso <hello@francescomancuso.it>
* @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<String> 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<String> 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.");
}
}
}

View File

@@ -0,0 +1,50 @@
/**
* @fileoverview Libreria Cryptea - Calcolo del digest SHA-512
*
* @author Francesco Mancuso <hello@francescomancuso.it>
* @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;
}
}

View File

@@ -0,0 +1,126 @@
/**
* @fileoverview Libreria Cryptea - Gestione delle chiavi nel formato Cryptea
*
* @author Francesco Mancuso <hello@francescomancuso.it>
* @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;
}
}

View File

@@ -0,0 +1,100 @@
/**
* @fileoverview Libreria Cryptea - Operazioni RSA cifratura / decifratura
*
* @author Francesco Mancuso <hello@francescomancuso.it>
* @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;
}
}

View File

@@ -0,0 +1,92 @@
/**
* @fileoverview Libreria Cryptea - Strumenti di conversione Base64
*
* @author Francesco Mancuso <hello@francescomancuso.it>
* @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);
}
}

View File

@@ -0,0 +1,55 @@
/**
* @fileoverview Libreria Cryptea - Algoritmo di Esponenziazione Modulare
*
* @author Francesco Mancuso <hello@francescomancuso.it>
* @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;
}
}

View File

@@ -0,0 +1,42 @@
/**
* @fileoverview Libreria Cryptea - Strumenti di conversione HEX
*
* @author Francesco Mancuso <hello@francescomancuso.it>
* @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);
}
}

View File

@@ -0,0 +1,76 @@
/**
* @fileoverview Libreria Cryptea - Strumenti di lavoro per JSON
*
* @author Francesco Mancuso <hello@francescomancuso.it>
* @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 <T> Il tipo dell'oggetto da estrarre
* @param json Stringa JSON
* @param clazz La classe che rappresenta la struttura dell'oggetto
* @return
*/
public static <T> T objectFromJson(String json, Class<T> 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);
}
}