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