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