1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
/* Author: Alberto Gil Tesa WebSite: http://giltesa.com License: CC BY-NC-SA 3.0 http://goo.gl/CTYnN File: Rsa.java Date: 26/02/2013 NOTAS: http://es.wikipedia.org/wiki/RSA */ import java.math.BigInteger; import java.security.SecureRandom; public class Rsa { private BigInteger n; // Clave compartida private BigInteger d; // Clave privada (no se comparte) private BigInteger k; // Clave publica para la otra parte private final int K = 0, D = 0, N = 1; /** * Constructor que genera las claves publica y privada de tamaño bitlen indicado. * * @param bitlen */ public Rsa(int bitlen) { // Calculamos los dos numeros primos p y q: SecureRandom r = new SecureRandom(); BigInteger p = new BigInteger(bitlen / 2, 100, r); BigInteger q = new BigInteger(bitlen / 2, 100, r); //n = p*q, v= (p-1)*(q-1) n = p.multiply(q); BigInteger v = ( p.subtract(BigInteger.ONE) ).multiply(q.subtract(BigInteger.ONE)); // Calculamos k como el numero impar mas pequeño relativamente primo con v k = new BigInteger("3"); while( v.gcd(k).intValue() > 1 ) k = k.add(new BigInteger("2")); // Calculamos d de modo que (d * k) MOD V = 1 d = k.modInverse(v); } /** * Pasa el BigInteger normal a cifrado usando la clave publica. * * @param message * @return */ public BigInteger encrypt(BigInteger message) { return message.modPow(k, n); } /** * Pasa el BigInteger normal a cifrado usando la clave publica recibida. * * @param message * @param key * @return */ public BigInteger encrypt(BigInteger message, BigInteger[] key) { return message.modPow(key[K], key[N]); } /** * Pasa el BigInteger de cifrado a normal usando la clave privada. * * @param message * @return */ public BigInteger decrypt(BigInteger message) { return message.modPow(d, n); } /** * Pasa el BigInteger de cifrado a normal usando la clave privada recibida. * * @param message * @return */ public BigInteger decrypt(BigInteger message, BigInteger[] key) { return message.modPow(key[D], key[N]); } /** * Devuelve la clave publica. * * @return */ public BigInteger[] getPublicKey() { return new BigInteger[] { k, n }; } /** * Devuelve la clave privada. * * @return */ public BigInteger[] getPrivateKey() { return new BigInteger[] { d, n }; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
/* Author: Alberto Gil Tesa WebSite: http://giltesa.com License: CC BY-NC-SA 3.0 http://goo.gl/CTYnN File: MainCifrar.java Date: 26/02/2013 */ import java.math.BigInteger; public class MainCifrar { public static void main(String[] args) { // Estos son los datos que se van a cifrar y descifrar: byte[] misDatos = new byte[] { 'H', 'o', 'l', 'a', ' ', 'm', 'u', 'n', 'd', 'o', '!' }; // Lo primero es crear dos objetos RSA, el primero hara de Cliente y el segundo de Servidor. // Cada uno cuenta con sus claves publicas y privadas generadas: Rsa rsaCliente = new Rsa(1024); Rsa rsaServidor = new Rsa(1024); // Cuando el Cliente cifra los datos lo hace con la clave publica del Servidor: BigInteger cifrado = rsaCliente.encrypt(new BigInteger(misDatos), rsaServidor.getPublicKey()); // Cuando el Servidor descifra los datos lo hace con su propia clave privada: BigInteger descifrado = rsaServidor.decrypt(cifrado); // Y por ultimo se imprime por pantalla el BigInteger pasandolo a un array de chars: byte[] array = descifrado.toByteArray(); // Se recorre el array: if( array.length > 0 ) { System.out.println("Mensaje:"); for( int i = 0 ; i < array.length ; i++ ) System.out.print((char)array[i]); } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
/* Author: Alberto Gil Tesa WebSite: http://giltesa.com License: CC BY-NC-SA 3.0 http://goo.gl/CTYnN File: MainCifrarFirmar.java Date: 26/02/2013 NOTAS: El cliente firma con su privada Despues cifra con la publica del servidor El servidor descifra con su privada Despues desfirma con la publica del cliente */ import java.math.BigInteger; public class MainCifrarFirmar { public static void main(String[] args) { // Estos son los datos que se van a cifrar y descifrar: byte[] misDatos = new byte[] { 'H', 'o', 'l', 'a', ' ', 'm', 'u', 'n', 'd', 'o', '!' }; // Lo primero es crear dos objetos RSA, el primero hara de Cliente y el segundo de Servidor. // Cada uno cuenta con sus claves publicas y privadas generadas: Rsa c = new Rsa(1024); Rsa s = new Rsa(1024); // El Cliente firma con su privada: BigInteger firmado = c.encrypt(new BigInteger(misDatos), c.getPrivateKey()); // El Cliente cifra con la publica del servidor: BigInteger cifrado = c.encrypt(firmado, s.getPublicKey()); // El Servidor usa su clave privada para descifrar: BigInteger descifrado = s.decrypt(cifrado); // El Servidor usa la clave publica del cliente para Desfirmar: BigInteger desfirmado = s.decrypt(descifrado, c.getPublicKey()); // Y por ultimo se imprime por pantalla el BigInteger pasandolo a un array de chars: byte[] array = desfirmado.toByteArray(); // Se recorre el array: if( array.length > 0 ) { System.out.println("Mensaje:"); for( int i = 0 ; i < array.length ; i++ ) System.out.print((char)array[i]); } } } |
Gracias Alberto, sin esta aportación me habría costado entenderlo bastante más (y hacer los ejercicios también, para que nos vamos a engañar xD).
He modificado un poquillo el ultimo main para añadir algo mas de seguridad.
http://pastebin.com/b2WYD1D1
Saludos y muchísimas gracias otra vez ^^
Exelente post!!! Gracias por compartir esta belleza de codigo.
Gracias por el post. Necesitaba un ejemplo explicado del código y lo he encontrado.