Upload files to "src"
This commit is contained in:
18
src/Caesar.java
Normal file
18
src/Caesar.java
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package com.crypto;
|
||||||
|
import java.util.Scanner;
|
||||||
|
public class Caesar {
|
||||||
|
|
||||||
|
public static void encode(Scanner sc){
|
||||||
|
String alphabet = "abcdefghijklmnopqrstuvwxyz";
|
||||||
|
System.out.println("Digita il testo in chiaro da cifrare:");
|
||||||
|
String base = sc.nextLine();
|
||||||
|
System.out.println("Digita il valore della chiave:");
|
||||||
|
int key = sc.nextInt();
|
||||||
|
char encoded[] = base.toCharArray();
|
||||||
|
|
||||||
|
for(int i = 0; i < base.length(); i++){
|
||||||
|
encoded[i] = alphabet.charAt(alphabet.indexOf(encoded[i]) + key % 26);
|
||||||
|
}
|
||||||
|
System.out.println(encoded);
|
||||||
|
}
|
||||||
|
}
|
||||||
140
src/Main.java
Normal file
140
src/Main.java
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
package com.crypto;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.util.Scanner;
|
||||||
|
|
||||||
|
public class Main {
|
||||||
|
|
||||||
|
// ─────────────────────────────────────────────
|
||||||
|
// Menu
|
||||||
|
// ─────────────────────────────────────────────
|
||||||
|
private static int scegliDimensioneChiave(Scanner scanner) {
|
||||||
|
int bits = 0;
|
||||||
|
|
||||||
|
while (bits == 0) {
|
||||||
|
System.out.println("\nSeleziona la dimensione della chiave:");
|
||||||
|
System.out.println(" [1] 512 bit (Solo uso didattico)");
|
||||||
|
System.out.println(" [2] 1024 bit (Deprecata, solo test)");
|
||||||
|
System.out.println(" [3] 2048 bit (Standard attuale)");
|
||||||
|
System.out.println(" [4] 3072 bit (Ottimo compromesso)");
|
||||||
|
System.out.println(" [5] 4096 bit (Alta sicurezza)");
|
||||||
|
System.out.print("Scelta (1-5): ");
|
||||||
|
|
||||||
|
try {
|
||||||
|
int scelta = Integer.parseInt(scanner.nextLine().trim());
|
||||||
|
|
||||||
|
// Assegniamo i bit in base alla scelta
|
||||||
|
switch (scelta) {
|
||||||
|
case 1 -> bits = 512;
|
||||||
|
case 2 -> bits = 1024;
|
||||||
|
case 3 -> bits = 2048;
|
||||||
|
case 4 -> bits = 3072;
|
||||||
|
case 5 -> bits = 4096;
|
||||||
|
default -> System.out.println("❌ Scelta non valida. Inserisci un numero da 1 a 5.");
|
||||||
|
}
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
System.out.println("❌ Errore: Inserisci un numero valido.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("Selezionata chiave da " + bits + " bit.");
|
||||||
|
return bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Main
|
||||||
|
public static void main(String[] args) {
|
||||||
|
Scanner scanner = new Scanner(System.in);
|
||||||
|
|
||||||
|
System.out.println("==========================================");
|
||||||
|
System.out.println(" RSA CRYPTO ENGINE ");
|
||||||
|
System.out.println("==========================================");
|
||||||
|
|
||||||
|
// --- 1. SETUP DELLE CHIAVI ---
|
||||||
|
int dimChiave = scegliDimensioneChiave(scanner);
|
||||||
|
|
||||||
|
System.out.println("\n⏳ Generazione delle chiavi in corso...");
|
||||||
|
// Passiamo dimChiave / 2 come facevi prima per p e q
|
||||||
|
RSA.RSAkeys chiavi = RSA.defkeys(dimChiave / 2);
|
||||||
|
System.out.println("> Chiavi generate con successo!");
|
||||||
|
|
||||||
|
boolean continua = true;
|
||||||
|
|
||||||
|
// --- CICLO PRINCIPALE ---
|
||||||
|
while (continua) {
|
||||||
|
|
||||||
|
System.out.println("\n------------------------------------------");
|
||||||
|
System.out.println("Cosa vuoi fare?");
|
||||||
|
System.out.println(" [1] Cifra un numero");
|
||||||
|
System.out.println(" [2] Cifra una stringa");
|
||||||
|
System.out.println(" [3] Rigenera le chiavi");
|
||||||
|
System.out.println(" [0] Esci");
|
||||||
|
System.out.println("------------------------------------------");
|
||||||
|
System.out.print("Scelta: ");
|
||||||
|
|
||||||
|
int scelta = -1;
|
||||||
|
try {
|
||||||
|
scelta = Integer.parseInt(scanner.nextLine().trim());
|
||||||
|
} catch (NumberFormatException ignored) {
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println();
|
||||||
|
|
||||||
|
switch (scelta) {
|
||||||
|
|
||||||
|
case 1 -> {
|
||||||
|
// MODALITÀ NUMERO
|
||||||
|
System.out.print("Inserisci il numero da cifrare: ");
|
||||||
|
try {
|
||||||
|
BigInteger m = new BigInteger(scanner.nextLine().trim());
|
||||||
|
|
||||||
|
System.out.println("> Cifratura in corso...");
|
||||||
|
BigInteger c = RSA.encrypt(m, chiavi.e(), chiavi.n());
|
||||||
|
System.out.println("Cifrato:\n" + c);
|
||||||
|
|
||||||
|
System.out.println("\n> Decifratura in corso...");
|
||||||
|
BigInteger dec = RSA.decrypt(c, chiavi.d(), chiavi.n());
|
||||||
|
System.out.println("Decifrato:\n" + dec);
|
||||||
|
|
||||||
|
} catch (IllegalArgumentException ex) {
|
||||||
|
System.out.println("> Errore: Assicurati di inserire un numero valido.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case 2 -> {
|
||||||
|
// MODALITÀ STRINGA
|
||||||
|
System.out.print("Inserisci il testo da cifrare: ");
|
||||||
|
String input = scanner.nextLine();
|
||||||
|
|
||||||
|
System.out.println("> Cifratura in corso...");
|
||||||
|
String cifrato = RSA.encrypt(input, chiavi.e(), chiavi.n());
|
||||||
|
if (cifrato != null && !cifrato.isEmpty()) {
|
||||||
|
// 2. SOLO PER LA STAMPA: nascondiamo il binario convertendolo in Base64
|
||||||
|
String base64 = java.util.Base64.getEncoder().encodeToString(cifrato.getBytes());
|
||||||
|
System.out.println("Cifrato (Base64):\n" + base64);
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("\n> Decifratura in corso...");
|
||||||
|
String dec = RSA.decrypt(cifrato, chiavi.d(), chiavi.n());
|
||||||
|
System.out.println("Decifrato:\n" + dec);
|
||||||
|
}
|
||||||
|
|
||||||
|
case 3 -> {
|
||||||
|
// RIGENERA CHIAVI
|
||||||
|
dimChiave = scegliDimensioneChiave(scanner);
|
||||||
|
System.out.println("\n> Generazione delle chiavi in corso...");
|
||||||
|
chiavi = RSA.defkeys(dimChiave / 2);
|
||||||
|
System.out.println("> Chiavi rigenerate con successo!");
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0 -> {
|
||||||
|
continua = false;
|
||||||
|
System.out.println("Chiusura del motore RSA. Alla prossima!");
|
||||||
|
}
|
||||||
|
|
||||||
|
default -> System.out.println("> Scelta non valida, riprova.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scanner.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
93
src/RSA.java
Normal file
93
src/RSA.java
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
package com.crypto;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
public class RSA {
|
||||||
|
|
||||||
|
// Struttura che rappresenta il mazzo di chiavi che viene generato con la
|
||||||
|
// funzione defkeys()
|
||||||
|
public record RSAkeys(BigInteger n, BigInteger e, BigInteger d) {}
|
||||||
|
|
||||||
|
static RSAkeys defkeys(int primesize) {
|
||||||
|
// Generiamo i numeri primi p e q, con la size scelta dall'utente
|
||||||
|
BigInteger p = Utilities.GenPrime(primesize);
|
||||||
|
BigInteger q = Utilities.GenPrime(primesize);
|
||||||
|
|
||||||
|
// Rigeneriamo q se p e q sono uguali (just in case)
|
||||||
|
while (p.equals(q)) {
|
||||||
|
q = Utilities.GenPrime(primesize);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calcoliamo n come prodotto pq
|
||||||
|
BigInteger n = p.multiply(q);
|
||||||
|
|
||||||
|
// Calcoliamo la funzione di Eulero phi (o m)
|
||||||
|
BigInteger phi = (p.subtract(BigInteger.ONE)).multiply((q.subtract(BigInteger.ONE)));
|
||||||
|
|
||||||
|
// Calcoliamo la chiave pubblica e, rendendola prima rispetto a phi
|
||||||
|
BigInteger e = Utilities.CalculateE(phi);
|
||||||
|
|
||||||
|
// Stampa i risultati per il debug
|
||||||
|
System.out.println("\n--- RISULTATI GENERAZIONE ---");
|
||||||
|
System.out.println("Bit di p generato: " + p);
|
||||||
|
System.out.println("Bit di q generato: " + q);
|
||||||
|
System.out.println("Bit del modulo n: " + n);
|
||||||
|
System.out.println("Bit di phi generato: " + phi);
|
||||||
|
System.out.println("Bit del modulo e: " + e);
|
||||||
|
|
||||||
|
// Calcoliamo la chiave privata d (o k)
|
||||||
|
BigInteger d = e.modInverse(phi);
|
||||||
|
|
||||||
|
return new RSAkeys(n, e, d);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------- Encrypting e Decrypting di valori numerici ----------------------------------
|
||||||
|
|
||||||
|
static BigInteger encrypt(BigInteger m, BigInteger e, BigInteger n) {
|
||||||
|
// Controllo vitale: m deve essere positivo e minore di n
|
||||||
|
if (m.compareTo(BigInteger.ZERO) < 0 || m.compareTo(n) >= 0) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Il messaggio deve essere positivo e minore del modulo n! - Cifratura annullata");
|
||||||
|
}
|
||||||
|
// Cifriamo con i nostri parametri kpb(e,n)
|
||||||
|
return m.modPow(e, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
static BigInteger decrypt(BigInteger c, BigInteger d, BigInteger n) {
|
||||||
|
// Decifriamo con i nostri parametri kpb(e,n)
|
||||||
|
return c.modPow(d, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------- Encrypting e Decrypting di valori alfanumerici ---------------------------
|
||||||
|
|
||||||
|
static String encrypt(String input, BigInteger e, BigInteger n) {
|
||||||
|
// Calcoliamo la lunghezza dei blocchi g e la approssimiamo per difetto
|
||||||
|
// basta contare i bit necessari per rappresentare n e poi fare - 1 perchè non ci serve la precisione
|
||||||
|
int g = n.bitLength() - 1;
|
||||||
|
if (g == 8)
|
||||||
|
g = 7;
|
||||||
|
|
||||||
|
// Conversione da stringhe a bytes( ASCII ma in decimale !)
|
||||||
|
byte[] m = input.getBytes();
|
||||||
|
|
||||||
|
// Conversione in Binario e unificazione in un unica stringa
|
||||||
|
String data = Utilities.BytestoBin(m);
|
||||||
|
|
||||||
|
// Divisione del messaggio e cifratura
|
||||||
|
String res = Utilities.DivideetImpera(data,g,e,n);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static String decrypt(String m, BigInteger d, BigInteger n) {
|
||||||
|
// Calcolo di z
|
||||||
|
int z = n.bitLength();
|
||||||
|
if (n.and(n.subtract(BigInteger.ONE)).equals(BigInteger.ZERO))
|
||||||
|
z--; // n è una potenza esatta di 2, togli 1
|
||||||
|
// Calcolo di g
|
||||||
|
int g = n.bitLength() - 1;
|
||||||
|
if (g == 8)
|
||||||
|
g = 7;
|
||||||
|
String res = Utilities.ImperaetDivide(m, z, g, d, n);
|
||||||
|
return res.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
62
src/Seal.java
Normal file
62
src/Seal.java
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
package com.crypto;
|
||||||
|
import io.javalin.Javalin;
|
||||||
|
|
||||||
|
public class Seal {
|
||||||
|
|
||||||
|
// Il mazzo di chiavi !!
|
||||||
|
public static RSA.RSAkeys keys;
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
// Avvio del server web
|
||||||
|
Javalin app = Javalin.create(config -> {
|
||||||
|
config.staticFiles.add("/get");
|
||||||
|
}).start(8080);
|
||||||
|
|
||||||
|
|
||||||
|
System.out.println("⏳ Generazione chiavi RSA per il server web in corso...");
|
||||||
|
|
||||||
|
// Cifratura con Cifrario di Cesare
|
||||||
|
app.post("/seal/caesar/encrypt", ctx -> {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
// Decifratura con Cifrario di Vigenere
|
||||||
|
app.post("/seal/vigenere/encrypt", ctx -> {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
// Cifratura con RSA
|
||||||
|
app.post("/seal/rsa/encrypt", ctx -> {
|
||||||
|
// Legge i dati nel body dalla richiesta
|
||||||
|
Richiesta req = ctx.bodyAsClass(Richiesta.class);
|
||||||
|
keys = RSA.defkeys(req.keysize / 2);
|
||||||
|
String ciphertext = RSA.encrypt(req.text,keys.e(), keys.n());
|
||||||
|
ctx.result(ciphertext);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Decifratura con RSA
|
||||||
|
app.post("/seal/rsa/decrypt", ctx -> {
|
||||||
|
// Legge i dati nel body dalla richiesta
|
||||||
|
Richiesta req = ctx.bodyAsClass(Richiesta.class);
|
||||||
|
|
||||||
|
// Usa il metodo RSA per cifrare
|
||||||
|
String plaintext = RSA.decrypt(req.text, keys.d(), keys.n());
|
||||||
|
|
||||||
|
// Restituisce il risultato della cifratura
|
||||||
|
ctx.result(plaintext.replaceAll("\\\\u0000", ""));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Classe utilizzata per tradurre il JSON - Rappresenta l'oggetto richiesta
|
||||||
|
class Richiesta {
|
||||||
|
public int keysize;
|
||||||
|
public String text;
|
||||||
|
|
||||||
|
// Costruttore della richiesta
|
||||||
|
public Richiesta() {}
|
||||||
|
}
|
||||||
116
src/Utilities.java
Normal file
116
src/Utilities.java
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
package com.crypto;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
|
||||||
|
public class Utilities {
|
||||||
|
|
||||||
|
static BigInteger GenPrime(int primesize) {
|
||||||
|
// 0. Inizializza il generatore crittograficamente sicuro di numeri casuali
|
||||||
|
SecureRandom sr = new SecureRandom();
|
||||||
|
|
||||||
|
// 1. Definizione della soglia di precisione
|
||||||
|
int precision = 100;
|
||||||
|
|
||||||
|
// Stampa di attesa
|
||||||
|
System.out.println("Generazione dei numeri primi in corso... (potrebbe richiedere qualche istante)");
|
||||||
|
|
||||||
|
// 2. Generazione della chiave
|
||||||
|
BigInteger prime = new BigInteger(primesize, precision, sr);
|
||||||
|
|
||||||
|
return prime;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Algoritmo visto in classe rimodellato per java
|
||||||
|
static BigInteger ModExp(BigInteger a, BigInteger b, BigInteger n) {
|
||||||
|
BigInteger result = BigInteger.valueOf(1);
|
||||||
|
a = a.mod(n);
|
||||||
|
while (b.compareTo(BigInteger.ZERO) > 0) {
|
||||||
|
// Se b è dispari
|
||||||
|
if (b.testBit(0)) {
|
||||||
|
result = result.multiply(a).mod(n);
|
||||||
|
}
|
||||||
|
a = (a.multiply(a)).mod(n);
|
||||||
|
// Dividiamo l'esponente per 2 spostando i bit (pare che sia più rapido in
|
||||||
|
// questo modo)
|
||||||
|
b = b.shiftRight(1);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BigInteger CalculateE(BigInteger phi) {
|
||||||
|
BigInteger e = BigInteger.valueOf(65537);
|
||||||
|
// Finchè il GCD (MCD) non è esattamente uguale a uno
|
||||||
|
while (!(e.gcd(phi).equals(BigInteger.ONE))) {
|
||||||
|
e = e.add(BigInteger.valueOf(7));
|
||||||
|
}
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String BytestoBin(byte[] m) {
|
||||||
|
StringBuilder sr = new StringBuilder();
|
||||||
|
for (byte b : m) {
|
||||||
|
// %8s significa stringa di 8 bit con eventuale padding a sinistra
|
||||||
|
// b viene messo in and con 0xFF che serve per forzare valori positivi
|
||||||
|
// il replace aggiunge il padding di zeri al posto degli spazi
|
||||||
|
sr.append(String.format("%8s", Integer.toBinaryString(b & 0xFF)).replace(' ', '0'));
|
||||||
|
}
|
||||||
|
return sr.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Converte i valori cifrati in binario e aggiunge il padding a sinistra fino a
|
||||||
|
// raggiungere il valore z
|
||||||
|
public static String BigIntToBin(BigInteger val, int g) {
|
||||||
|
String bin = val.toString(2);
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
// aggiungi zeri a sinistra fino a g
|
||||||
|
for (int i = bin.length(); i < g; i++) {
|
||||||
|
sb.append('0');
|
||||||
|
}
|
||||||
|
sb.append(bin);
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Divisione in blocchi e applicazione dell'algoritmo visto in classe per la cifratura
|
||||||
|
|
||||||
|
public static String DivideetImpera(String data, int g, BigInteger e, BigInteger n) {
|
||||||
|
StringBuilder res = new StringBuilder();
|
||||||
|
int i;
|
||||||
|
// Calcolo di z
|
||||||
|
int z = n.bitLength();
|
||||||
|
if (n.and(n.subtract(BigInteger.ONE)).equals(BigInteger.ZERO))
|
||||||
|
z--; // n è una potenza esatta di 2, togli 1
|
||||||
|
|
||||||
|
for (i = 0; (i + g) <= data.length(); i += g) {
|
||||||
|
String block = data.substring(i, i + g);// prendo il blocco
|
||||||
|
BigInteger val = new BigInteger(block, 2);// converto in binario
|
||||||
|
res.append(BigIntToBin(val.modPow(e, n), z));
|
||||||
|
}
|
||||||
|
if (i < data.length()) {
|
||||||
|
String b = data.substring(i, data.length());
|
||||||
|
while (g != b.length()) {
|
||||||
|
b += '0';
|
||||||
|
}
|
||||||
|
BigInteger val = new BigInteger(b, 2);// converto in binario
|
||||||
|
res.append(BigIntToBin(val.modPow(e, n), z));
|
||||||
|
}
|
||||||
|
return res.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Divisione in blocchi e applicazione dell'algoritmo visto in classe per la decifratura
|
||||||
|
|
||||||
|
public static String ImperaetDivide(String data, int z,int g, BigInteger e, BigInteger n) {
|
||||||
|
StringBuilder res = new StringBuilder();
|
||||||
|
for (int i = 0; (i + z) <= data.length(); i += z) {
|
||||||
|
BigInteger val = new BigInteger(data.substring(i, i + z), 2);
|
||||||
|
res.append(BigIntToBin(val.modPow(e, n), g));
|
||||||
|
}
|
||||||
|
StringBuilder testo = new StringBuilder();
|
||||||
|
for (int i = 0; i + 8 <= res.length(); i += 8) {
|
||||||
|
String block = res.substring(i, i + 8);
|
||||||
|
int ascii = Integer.parseInt(block, 2);
|
||||||
|
testo.append((char) ascii);
|
||||||
|
}
|
||||||
|
return testo.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user