jueves, 13 de agosto de 2015

CIFRADO RSA

RSA es uno de los sistemas de cifrado (encriptación) asimétricos, más exitosos en la actualidad. Originalmente descubierto 1973 por la agencia de inteligencia británica GCHQ, Government Communications Headquarters (GCHQ), recibió la clasificación de alto secreto “Top Secret”.
 El algoritmo fue descrito en 1977 y es propiedad de los criptólogos Ron Rivest,  Adi Shamir y Leonard Adleman,  del Instituto Tecnológico de Massachusetts (MIT) - RSA sol las letras iniciales de sus apellidos.

El algoritmo fue patentado por MIT en 1983 y no fue revelado hasta 1997. A diferencia de los sistemas de codificación simétrica tradicionales, RSA trabaja con dos claves diferentes: una clave "pública", y otra "privada". Ambas son complementarias entre sí (trabajan de manera conjunta) así que un mensaje cifrado con una de ellas sólo puede ser descifrado por su contraparte. Dado que la clave privada no se puede calcular a partir de la clave pública, esta última queda generalmente queda a disposición del público. Estas propiedades permiten que los cripto-sistemas asimétricos sean utilizados en una amplia variedad de funciones, tales como las firmas digitales.


Algoritmo RSA:

El Algoritmo RSA Consta de 3 partes, la primera hace referencia a la generación de las claves o llaves que serán usadas para la encriptación  del mensaje, la segunda el proceso de encriptado y la tercera el proceso de desencriptar el mensaje.


Generación de las Llaves (Pública y Privada).



























Para generar un par de claves (KP ; Kp), en primer lugar se eligen aleatoriamente dos números primos grandes, p y q (de unas 200 cifras cada uno, por ejemplo). Después se calcula el producto n = p.q Escogeremos ahora un número e primo relativo con (p-1) y con (q-1). Este par de números (e,n) pueden ser conocidos por cualquiera, y constituyen la llamada clave pública e por tanto debe tener un inverso módulo (p-1)(q-1), al que llamamos d. Por supuesto se cumple que ed ≡ 1 mod((p-1)(q-1)), que es lo mismo que decir que ed = 1+k (p-1)(q-1) para algún entero k. La clave privada será el par (d,n). Este número d debe mantenerse secreto y sólo será conocido por el propietario del par de claves.


Proceso de Encriptación y Desencriptación del Mensaje






















Ejemplo Aplicativo:


























Implementación


Clase Conversor
public class Conversor {
    public int numero(String a){
        int C=-666;
        if(a.equals(" ")){
            C=-555;
        }else if(a.equals("a")||a.equals("A")){
            C=0;
        }else if(a.equals("b")||a.equals("B")){
            C=1;
        }else if(a.equals("c")||a.equals("C")){
            C=2;
        }else if(a.equals("d")||a.equals("D")){
            C=3;
        }else if(a.equals("e")||a.equals("E")){
            C=4;
        }else if(a.equals("f")||a.equals("F")){
            C=5;
        }else if(a.equals("g")||a.equals("G")){
            C=6;
        }else if(a.equals("h")||a.equals("H")){
            C=7;
        }else if(a.equals("i")||a.equals("I")){
            C=8;
        }else if(a.equals("j")||a.equals("J")){
            C=9;
        }else if(a.equals("k")||a.equals("K")){
            C=10;
        }else if(a.equals("l")||a.equals("L")){
            C=11;
        }else if(a.equals("m")||a.equals("M")){
            C=12;
        }else if(a.equals("n")||a.equals("N")){
            C=13;
        }else if(a.equals("o")||a.equals("O")){
            C=14;
        }else if(a.equals("p")||a.equals("P")){
            C=15;
        }else if(a.equals("q")||a.equals("Q")){
            C=16;
        }else if(a.equals("r")||a.equals("R")){
            C=17;
        }else if(a.equals("s")||a.equals("S")){
            C=18;
        }else if(a.equals("t")||a.equals("T")){
            C=19;
        }else if(a.equals("u")||a.equals("U")){
            C=20;
        }else if(a.equals("v")||a.equals("V")){
            C=21;
        }else if(a.equals("w")||a.equals("W")){
            C=22;
        }else if(a.equals("x")||a.equals("X")){
            C=23;
        }else if(a.equals("y")||a.equals("Y")){
            C=24;
        }else if(a.equals("z")||a.equals("Z")){
            C=25;
        }
        return C;
    }
    
    public String numeroletra(int a){
        String C=null;
        if(a==-555){
            C=" ";
        }else if(a==0){
            C="00";
        }else if(a==1){
            C="01";
        }else if(a==2){
            C="02";
        }else if(a==3){
            C="03";
        }else if(a==4){
            C="04";
        }else if(a==5){
            C="05";
        }else if(a==6){
            C="06";
        }else if(a==7){
            C="07";
        }else if(a==8){
            C="08";
        }else if(a==9){
            C="09";
        }else if(a==10){
            C="10";
        }else if(a==11){
            C="11";
        }else if(a==12){
            C="12";
        }else if(a==13){
            C="13";
        }else if(a==14){
            C="14";
        }else if(a==15){
            C="15";
        }else if(a==16){
            C="16";
        }else if(a==17){
            C="17";
        }else if(a==18){
            C="18";
        }else if(a==19){
            C="19";
        }else if(a==20){
            C="20";
        }else if(a==21){
            C="21";
        }else if(a==22){
            C="22";
        }else if(a==23){
            C="23";
        }else if(a==24){
            C="24";
        }else if(a==25){
            C="25";
        }
        return C;
    }
    
    public String letranumero(int a){
        String C=null;
        if(a==-555){
            C=" ";
        }else if(a==0){
            C="A";
        }else if(a==1){
            C="B";
        }else if(a==2){
            C="C";
        }else if(a==3){
            C="D";
        }else if(a==4){
            C="E";
        }else if(a==5){
            C="F";
        }else if(a==6){
            C="G";
        }else if(a==7){
            C="H";
        }else if(a==8){
            C="I";
        }else if(a==9){
            C="J";
        }else if(a==10){
            C="K";
        }else if(a==11){
            C="L";
        }else if(a==12){
            C="M";
        }else if(a==13){
            C="N";
        }else if(a==14){
            C="O";
        }else if(a==15){
            C="P";
        }else if(a==16){
            C="Q";
        }else if(a==17){
            C="R";
        }else if(a==18){
            C="S";
        }else if(a==19){
            C="T";
        }else if(a==20){
            C="U";
        }else if(a==21){
            C="V";
        }else if(a==22){
            C="W";
        }else if(a==23){
            C="X";
        }else if(a==24){
            C="Y";
        }else if(a==25){
            C="Z";
        }
        return C;
    }
    
}

Clase Euclides
public class Euclides {
public long[] euclidesExtendido(long a, long b) 
{
 long[] resp = new long[3];
 long x=0,y=0,d=0;
 if(b==0)
 {
  resp[0] = a; resp[1] = 1; resp[2] = 0;
 } 
 else
 {
  long x2 = 1, x1 = 0, y2 = 0, y1 = 1;
  long q = 0, r = 0;
  while(b > 0)
  {
   q = (a/b);
   r = a - q*b;
   x = x2-q*x1;
   y = y2 - q*y1;
   a = b;
   b = r;
   x2 = x1;
   x1 = x;
   y2 = y1;
   y1 = y;
  }
  resp[0] = a;
  resp[1] = x2;
  resp[2] = y2;
    }
 return resp;  
    } 
}

Clase Exponenciación
public int CalcularExp(int a,int k,int z)
    {
        int exp=1;
        int xp=a%z;
        while(k > 0)
        {
            if((k%2)!=0)
            {
                exp=(exp*xp)%z;
            }
            xp=(xp*xp)%z;
            k=k/2;
        }
        return exp;
    }

Clase Inverso
public class Inverso {
    public double CalcularInverso(long n,long z)
    {
        long mcd[] =new long[3];
        int x=0,y = 0;
        Euclides obj = new Euclides();
        if(n > z)
        {
            mcd=obj.euclidesExtendido(n,z);
        }
        if(n < z)
        {
            mcd=obj.euclidesExtendido(z,n);
        }
        if(mcd[0] > 1)
        {
            System.out.println("EL INVERSO NO EXISTE");
            y=0;
        }
        else
        {
            y=(int) mcd[2];
            if(y < 0)
            {
                y=(int) (y+z);
            }
        }
        return y;
    }
}


Clase RSA
import java.util.ArrayList;
public class RSA {
    private long n, q, p;
    private long fi,e,d;
    private String mensaje;
    private String cifrado;
    private String MensajeLimpio;
    private String num_letra;
    private String CadenaDescifradaNumeros;
    public RSA()
    {
        //this.p=43;
        //this.q=59;
        //this.e=13;
        GenerarKey();
    }

    public String getCadenaDescifradaNumeros() {
        return CadenaDescifradaNumeros;
    }

    public String getNum_letra() {
        return num_letra;
    }



    public String getMensajeLimpio() {
        return MensajeLimpio;
    }

    public long getN() {
        return n;
    }

    public long getQ() {
        return q;
    }

    public long getP() {
        return p;
    }

    public long getFi() {
        return fi;
    }

    public long getE() {
        return e;
    }

    public long getD() {
        return d;
    }

    public String getMensaje() {
        return mensaje;
    }

    public String getCifrado() {
        return cifrado;
    }
    public void RecibirMensaje(String m)
    {
        this.mensaje=m;
    }
    public void RecibirCifrado(String c)
    {
        this.cifrado=c;
    }
    public boolean primo(int n)
    {
 for(int i=2;i < n;i++)
        {
            if(n%i==0)
            {
                return false;
            }
        }
 return true;
    }
    public void GenerarPrimos()
    {
        Boolean resP,resQ;
        do
        {
            p = (int)(Math.random()*(100-10+1)+10); 
            q = (int)(Math.random()*(100-10+1)+10); 
            resP=primo((int) p);
            resQ=primo((int) q);
        }while((p==q)||(resP==false)||(resQ==false));
        System.out.println("P:"+p);
        System.out.println("Q:"+q);
    }
    public int GenerarE()
    {
        Boolean resE;
        long mcd[]= new long[3];
        Euclides euclides = new Euclides();
        do
        {
            e = (int)(Math.random()*(100-1+1)+1);
            resE=primo((int) e);
            mcd=euclides.euclidesExtendido(e, fi);
        }while((e > =fi)||(mcd[0]!=1)||(resE==false));
        return (int) e;
    }
    public void GenerarKey()
    {
        GenerarPrimos();
        Inverso inverso= new Inverso();
        n=p*q;
        fi=(p-1)*(q-1);
        e=GenerarE();
        d=(long) inverso.CalcularInverso(e,fi);
        if(d < 0)
        {
            d=d+fi;
        }  
        System.out.println("n: "+n);
        System.out.println("fi: "+fi);
        System.out.println("e: "+e);
        System.out.println("d: "+d);
    }
    public String EliminarEspaciosCaracteresEspeciales()
    {
        //Eliminando los espacios y caracteres especiales
        String AlfabetoValido="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
        String aux_mensaje="";
        int contador=0;
        for(int i=0;i < mensaje.length();i++)
        {
            for(int j=0;j < AlfabetoValido.length();j++)
            {
                if(!String.valueOf(mensaje.charAt(i)).equals(String.valueOf(AlfabetoValido.charAt(j))))
                {
                    contador++;
                }
            }
            if(contador > =AlfabetoValido.length())
            {
                //AL EVALUAR EL CARACTER CON TODOS LOS ELEMENTOS DE LA CADENA UNA DEBE DE COINCIDIR POR LO QUE EL VALOR DEL CONTADOR DEBE SER UNO MENOS QUE
                //EL DEL TAMAÑO DE ALFABETOVALIDO, SI SON IGUALES O ES MAYOR SIGNIFICA QUE ESE CARACTER NO ES VALIDO Y DEBE SER IGNORADO
            }
            else
            {
                aux_mensaje=aux_mensaje+mensaje.charAt(i);//CREANDO UNA NUEVA CADENA SIN ESPACIOS
            }
            contador=0;
        }
        //En el caso de que falten caracteres para la agrupacion de 4, se completan con un x
        if(aux_mensaje.length()%2!=0)
        {
            aux_mensaje=aux_mensaje+"X";
        }
        return aux_mensaje;
    }
    public String ConvertirNumeros(String mensaje_sin_espacios)
    {
        int aux_num_letra;
        num_letra ="";
        Conversor letras= new Conversor();
        for(int i=0;i < mensaje_sin_espacios.length();i++)
        {
            //Realizando la conversion a numeros
            aux_num_letra=letras.numero(String.valueOf(mensaje_sin_espacios.charAt(i)));
            num_letra=num_letra+letras.numeroletra(aux_num_letra);
           
        }
        return num_letra;
    }
    public String ConvertirCadena(String cadenacifrada)
    {
        Conversor letras= new Conversor();
        int inicioC=0,finalC=2;
        String TextoCifrado="",aux_TextoCifrado;
        for(int i=0;i < cadenacifrada.length();i++)
        {
            aux_TextoCifrado=cadenacifrada.substring(inicioC,finalC);
            if(Integer.parseInt(aux_TextoCifrado) > 25)
            {
                aux_TextoCifrado=String.valueOf(Integer.parseInt(aux_TextoCifrado)%26);
            }
            TextoCifrado=TextoCifrado+letras.letranumero(Integer.parseInt(aux_TextoCifrado));//CREANDO UNA NUEVA CADENA SIN ESPACIOS
            inicioC=finalC;
            finalC=finalC+2;
            i=inicioC;
        }
        return TextoCifrado;
    }
    public String Cifrar(String num_letra)
    {
        Exponenciacion expo= new Exponenciacion();
        ArrayList < String >  Cifrado = new ArrayList <  > ();
        int inicioC=0,finalC=4,rexpo = 0;
        String auxiliar;
        for(int i =0 ;i < num_letra.length();i++)
        {
            auxiliar=num_letra.substring(inicioC,finalC);
            System.out.println("SUBCADENA ANTES DE CIFRAR: "+auxiliar);
            //Realizando operacion de encriptado
            rexpo=expo.CalcularExp(Integer.parseInt(auxiliar),(int)e,(int)n);
            System.out.println("YA ME CIFRARON: "+rexpo);
            //ALMACENANDO
            if(String.valueOf(rexpo).length()==1)
            {
                Cifrado.add("000"+String.valueOf(rexpo));
            }
            if(String.valueOf(rexpo).length()==2)
            {
                Cifrado.add("00"+String.valueOf(rexpo));
            }
            if(String.valueOf(rexpo).length()==3)
            {
                Cifrado.add("0"+String.valueOf(rexpo));
            }
            if(String.valueOf(rexpo).length()==4)
            {
                Cifrado.add(String.valueOf(rexpo));
            }
            inicioC=finalC;
            finalC=finalC+4;
            i=inicioC;
        }
        //Guardando todo en una sola cadena
        String cadena="";
        for(int i=0;i < Cifrado.size();i++)
        {
            cadena=cadena+Cifrado.get(i);
        }
        System.out.println("A MI TIENEN QUE DESCIFRARME: "+cadena);
        RecibirCifrado(cadena);//SALVANDO C , QUE SERA USADO PARA DESENCRIPTAR
        return cadena; 
    }
    public String Descifrar()
    {
        Exponenciacion expo= new Exponenciacion();
        ArrayList < String >  Descifrado = new ArrayList <  > ();
        int inicioC=0,finalC=4,rexpo = 0;
        String auxiliar;
        System.out.println("SOY EL MENSAJE CIFRADO: "+cifrado);
        for(int i =0 ;i < cifrado.length();i++)
        {
            auxiliar=cifrado.substring(inicioC,finalC); 
            System.out.println("SOY UNA SUBCADENA DEL MENSAJE CIFRADO ANTES DE SER DESCIFRADO: "+auxiliar);
            //Realizando operacion de encriptado
            rexpo=expo.CalcularExp(Integer.parseInt(auxiliar),(int)d,(int)n);
            System.out.println("ME DESCIFRARON: "+rexpo);
            //ALMACENANDO
            if(String.valueOf(rexpo).length()==1)
            {
                Descifrado.add("000"+String.valueOf(rexpo));
            }
            if(String.valueOf(rexpo).length()==2)
            {
                Descifrado.add("00"+String.valueOf(rexpo));
            }
            if(String.valueOf(rexpo).length()==3)
            {
                Descifrado.add("0"+String.valueOf(rexpo));
            }
            if(String.valueOf(rexpo).length()==4)
            {
                Descifrado.add(String.valueOf(rexpo));
            }
            inicioC=finalC;
            finalC=finalC+4;
            i=inicioC;
        }
        //Guardando todo en una sola cadena
        String cadena="";
        for(int i=0;i < Descifrado.size();i++)
        {
            cadena=cadena+Descifrado.get(i);
        }
        return cadena; 
    }
    public String OperacionRSAEncriptar()
    {
        //Generando llaves - ESTE PROCESO SE REALIZA EN EL METODO CONSTRUCTOR , AQUI SOLO LO INDICAMOS
        //Eliminando espacios y caracteres especiales
        MensajeLimpio=EliminarEspaciosCaracteresEspeciales();
        //Realizando conversion de texto a numeros
        System.out.println("SOY EL MENSAJE LIMPIO: "+MensajeLimpio);
        num_letra=ConvertirNumeros(MensajeLimpio);
        System.out.println("CADENA ANTERIOR PERO EN NUMEROS: "+num_letra);
        //Cifrando
        String cadena;
        cadena=Cifrar(num_letra);
        System.out.println("Soy el cifrado"+this.cifrado);
        //Realizando conversion de numeros a letras
        String TextoFinal;
        TextoFinal=ConvertirCadena(cadena);
        return TextoFinal;
    }
    public String OperacionRSADesencriptar()
    {
        CadenaDescifradaNumeros=Descifrar();
        String TextoFinal;
        TextoFinal=ConvertirCadena(CadenaDescifradaNumeros);
        return TextoFinal;
    }
}

RESULTADOS:



banner
Previous Post
Next Post

Hola, me llamo Andrés.Soy egresado de la carrera de Ingeniería Informática en la Universidad Nacional de Trujillo (Perú).Me considero autodidacta de corazón ,amante del mundo de la programación, software libre y hacking ético

3 comentarios:

  1. Si bien es cierto, el sistema de proceso de encriptacion, que aplicas en el ejemplo anterior, funciona perfectamente, debes de tener en cuenta que si queremos usarlo para encriptar una conversacion, deberas adaptar el codigo de tal manera que los "espacios" en blanco " " (Notese el espacio dejado en blanco entre las comillas) deberan ser encriptados de alguna manera para asi poder facilitar la lectura.

    ResponderEliminar
  2. Que chido, esto es mi proyecto final de Estructuras Discretas :)

    ResponderEliminar