[1.0.0] New jar file and directory
This commit is contained in:
BIN
source/cryptea-tools-1.0.0.jar
Normal file
BIN
source/cryptea-tools-1.0.0.jar
Normal file
Binary file not shown.
43
source/pom.xml
Normal file
43
source/pom.xml
Normal 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>
|
||||
313
source/src/main/java/tools/cryptea/Certificate.java
Normal file
313
source/src/main/java/tools/cryptea/Certificate.java
Normal 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.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
50
source/src/main/java/tools/cryptea/Digest.java
Normal file
50
source/src/main/java/tools/cryptea/Digest.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
126
source/src/main/java/tools/cryptea/Keys.java
Normal file
126
source/src/main/java/tools/cryptea/Keys.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
100
source/src/main/java/tools/cryptea/RSA.java
Normal file
100
source/src/main/java/tools/cryptea/RSA.java
Normal 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;
|
||||
}
|
||||
}
|
||||
92
source/src/main/java/tools/cryptea/utils/Base64Helper.java
Normal file
92
source/src/main/java/tools/cryptea/utils/Base64Helper.java
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
55
source/src/main/java/tools/cryptea/utils/EspMod.java
Normal file
55
source/src/main/java/tools/cryptea/utils/EspMod.java
Normal 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;
|
||||
}
|
||||
}
|
||||
42
source/src/main/java/tools/cryptea/utils/HexHelper.java
Normal file
42
source/src/main/java/tools/cryptea/utils/HexHelper.java
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
76
source/src/main/java/tools/cryptea/utils/JsonHelper.java
Normal file
76
source/src/main/java/tools/cryptea/utils/JsonHelper.java
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user