Implementação do RSA em Java O programa a seguir foi elaborado e testado pelo aluno de iniciação científica Breno Pompeu Roberto, sob a orientação do Prof. Routo Terada (IME-USP). /* RSA por Breno Pompeu Roberto Compilar: % javac RSA.java Executar: % java RSA */ import java.math.BigInteger; import java.util.Random; class RSA { private static int KEY_LENGTH = 128; /** * Método principal, responsável pelo * teste do programa */ public static void main(String args[]) { System.out.println("RSA CRYPTOSYSTEM"); KeyRSA keys[]; try { keys = RSA.createKeys(KEY_LENGTH); System.out.println("Encript Key ="+keys[0]); System.out.println("Decript Key ="+keys[1]); Random rd =new Random(System.currentTimeMillis()); EngineRSA eng = EngineRSA.create(keys,keys[1]); BigInteger t1,t2,t3; t1 = new BigInteger(128,rd); t2 = eng.encript(t1); t3 = eng.decript(t2); System.out.println("plain ="+t1.toString(36)); System.out.println("cipher ="+t2.toString(36)); System.out.println("plain ="+t3.toString(36)); } cath (Exception e) {e.printStackTrace();} } private static int CERTAINTY = 100; /** * Método responsável pela criação de chaves. */ public static KeyRSA[] createKeys(int bitLength) throws ArithmeticException { BigInteger p, q; BitInteger e, d, n; // Verifica se bitLength é válido // bitLength é o tamanho aproximado da chave if (bitLength < 2) throw (new ArithmeticException("Err: bitLength inválido.")); // inicializa o gerador de números aleatórios Random rd; rd = new Random(System.currentTimeMillis()); // encontra três números primos (p, q, d) diferentes, // e garante que o maior será o d. BigInteger t1, t2, t3; t1 = new BigInteger(bitLength, CERTAINTY, rd); t2 = new BigInteger(bitLength, CERTAINLY, rd); t3 = new BigInteger(bitLength, CERTAINTY, rd); while (true) { int c12, c13,c23; c12 = t1.compareTo(t2); c13 = t1.compareTo(t3); c23 = t2.compareTo(t3); if ( c12!=0 && c13!=0 && c23!=0) { if (c12==1 && c13==1) { d = t1; p = t2; q = t3; } else if (c23==1) { d = t2; p = t1; q = t3; } else { d = t3; p = t1; q = t2; } break; } else if (c12==0 || c13==0) { t1 = new BigInteger(bitLength, CERTAINTY, rd); } else { t2 = new BigInteger(bitLength, CERTAINTY, rd); } // encontra o valor de Phi = (p-1)*(q-1) BigInteger Phi; BigInteger unid = new BigInteger("1"); Phi = (p.subtract(unid)).multiply(q.subtract(unid)); // calcula o valor de e. e = d.modInverse(Phi); // calcula n = p*q n = p.multiply(q); // cria as duas chaves, a de criptografia e a // de decriptografia KeyRSA keys[] = new KeyRSA[2]; keys[0] = KeyRSA.create(e, n); keys[1] = KeyRSA.create(d, n); return keys; } } /** * Classe responsável por cripto. e decripto. números. */ class EngineRSA { private KeyRSA e; private KeyRSA d; public static EngineRSA create(KeyRSA e, KeyRSA d) { if (e == null || d == null) return null; return (new EngineRSA(e,d)); } private EngineRSA(KeysRSA e, KeyRSA d) { this.e = e; this.d=d; } BigInteger encript(BigInteger plain) { return plain.modPow(e.getKey(), e.getModulo()); } BigInteger decript(BigInteger cipher) { return cipher.modPow(d.getKey(), d.getModulo()); } } /** * Classe coma responsabilidade de guardar as chaves. */ class KeyRSA { // base em que vão ser impressos os números. private static int BASE_PRINT = 36; private BigInteger k; // chave private BigInteger n; // modulo public static KeyRSA create(BigInteger k, BigInteger n) { return (new KeyRSA(k,n)); } private KeyRSA create(BigInteger k, BigInteger n) { this.k = k; this.n = n; } public String toString() { return "{["+k.toString(KeyRSA.BASE_PRINT) +" ][ "+n.toString(KeyRSA.BASE_PRINT)+"]}; } BigInteger getKey() { return k; } BigInteger getModulo() { return n; } }