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:



jueves, 30 de julio de 2015

CIFRADO DE RABIN

El criptosistema de Rabin es una técnica criptográfica asimétrica cuya seguridad, al igual que RSA, se basa en la complejidad de la factorización. Sin embargo, la ventaja del criptosistema de Rabin es que se ha demostrado que la complejidad del problema en el que se basa es tan duro como la factorización de enteros, cosa que se desconoce si es cierto en el caso del RSA simple. El inconveniente que tiene es que cada salida de la función de Rabin puede ser generado por 4 posibles entradas, y si cada salida es un texto cifrado se requiere un tiempo extra en el descifrado para identificar cual de las 4 posibles entradas era el correcto texto en claro. El algoritmo se publicó en enero de 1979 por Michael O. Rabin.
El sistema de llave asimétrica de Rabin se basa en el problema de calcular raíces cuadradas módulo un número compuesto. Este problema se ha demostrado que es equivalente al de la factorización de dicho número.

ALGORITMO DE RABIN

GENERACIÓN DE LLAVES
Escogemos dos números primos, p y q, ambos congruentes con 3 módulo 4.Estos primos son la clave privada.
La clave pública es su producto, n=p*q.

CIFRAR MENSAJE

  • Cabe aclarar  que para cifrar el mensaje este debe de estar en forma de cadena de bits con una longitud de 16 bits , en el caso de que falten se cogen las ultimas cifras de la cadena para completar los 16 bits. 
  • Se realiza una conversión de binario a decimal de la cadena ingresada (m) .
  • Para codificar un mensaje , simplemente se calcula:

DESCIFRAR MENSAJE
Para desencriptar el mensaje solo se deben obtener las 4 raíces de:

C (mod n)

Una de las raíces convertida a binario hará referencia al mensaje cifrado.

EJEMPLO APLICATIVO:
Generando llaves:


Sea:
  • p=277
  • q=331
Entonces n= p*q = 91687

  • Clave Publica=(p=277,q=331)
  • Clave Privada=(n=91687)

Cifrando:

Cadena Ingresada: 1001111001 , como no cumple con la cantidad maxima de 16 caracteres se cogen las ultimas  6 cifras para completar, obteniendo nuestra nueva cadena:1001111001111001.
Pasando a decimal nuestra cadena, obteniendo m= 40569.
Ahora procedemos a cifrar: aplicando :
C=40569 mod 91687  =  62111

Descifrando:
Para descifrar el mensaje lo único que debemos hacer es aplicar la raíz cuadrada de C(mod n) , en este ejemplo obtendríamos:

m1 = 69654   = > 10001000000010110
m2 = 22033   = > 101011000010001
m3 = 40569   = > 1001111001111001
m4 = 51118   = > 1100011110101110

Podemos observar que la raíz m3 corresponde al mensaje antes de cifrar.


Implementación
Se hace recordar que en la implementacion hace uso de algoritmos que ya hemos visto con anterioridad , por lo que recomendamos se pase por el siguiente post:




Clase Rabin:

public class Rabin {
    private String mensaje;
    private long n, q, p;
    private String cifrado;
    private String CadenaCompleta;
    private int m,c;

    public int getM() {
        return m;
    }

    public int getC() {
        return c;
    }

    public String getCadenaCompleta() {
        return CadenaCompleta;
    }
    
    public String getMensaje() {
        return mensaje;
    }

    public long getN() {
        return n;
    }

    public long getQ() {
        return q;
    }

    public long getP() {
        return p;
    }

    public String getCifrado() {
        return cifrado;
    }
    
    public void setMensaje(String mensaje) {
        this.mensaje = mensaje;
    }
    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()*(1000-100+1)+100); 
            q = (int)(Math.random()*(1000-100+1)+100); 
            resP=primo((int) p);
            resQ=primo((int) q);
        }while((p< q)||(p==q)||(resP==false)||(resQ==false)||((p-3)%4!=0)||((q-3)%4!=0));
        
        System.out.println("P:"+p);
        System.out.println("Q:"+q);
    }
    public void GenerarKey()
    {
        GenerarPrimos();
        n=p*q;
        System.out.println("n: "+n);
    }
    public String CompletarCadena()
    {
        String nuevo_mensaje,aux;
        int tam=mensaje.length();
        int diferencia=tam-(16-tam);
        System.out.println("diferencia: "+diferencia);
        if(tam< 16)
        {
            aux=mensaje.substring(diferencia,tam);
            nuevo_mensaje=mensaje+aux;
        }
        else
        {
            nuevo_mensaje=mensaje;
        }
        return nuevo_mensaje;
    }
    public String Encriptar()
    {
        //Completando Cadena en el caso de que no cumplan los 16 bits   
        CadenaCompleta=CompletarCadena();
        //Pasando la cadena a decimal para poder encriptar
        Binario objBinario= new Binario();
        m=objBinario.BinarioDecimal(CadenaCompleta);
        //Encriptando
        Exponenciacion expo= new Exponenciacion();
        c=expo.CalcularExp(m, 2, (int) n);
        //Pasando a Binario el mensaje cifrado
        cifrado=objBinario.decimalABinario(c);
        return cifrado;
    }
    public String[] Desencriptar(int m,int c)
    {
        RaizCompuesta obj = new RaizCompuesta();
        int raices[]=new int[4];
        Binario objBinario= new Binario();
        String Descifrado[]= new String[4];
        raices=obj.CalcularRaizCompuesta(m,c);
        if(raices==null)
        {
            JOptionPane.showMessageDialog(null, "NO EXISTEN RAICES");
        }
        else
        {
            
            Descifrado[0]=objBinario.decimalABinario(raices[0]);
            Descifrado[1]=objBinario.decimalABinario(raices[1]);
            Descifrado[2]=objBinario.decimalABinario(raices[2]);
            Descifrado[3]=objBinario.decimalABinario(raices[3]);
        }
        return Descifrado;
    }
}


Clase Binario:
public class Binario {
    int decimal;
    public int BinarioDecimal(String numero)
    {
        decimal= Integer.parseInt(numero,2);
        return decimal;
    }
    public String decimalABinario(int numeroDecimal){
    int temp = numeroDecimal;
    String resultado="";
    while (temp != 0){
     if(temp % 2 == 0)
     {
         resultado="0"+resultado;
     }
     else
     {
         resultado="1"+resultado;
     }
     temp = temp/2;
    }
    return resultado;
   }
}

Resultados:




miércoles, 29 de julio de 2015

CIFRADO DE HILL

Fue Inventado por Lester S. Hill en 1929, y fue el primer sistema criptográfico polialfabético que era práctico para trabajar con mas de tres símbolos simultáneamente.
Este sistema es polialfabético pues puede darse que un mismo caracter en un mensaje a enviar se encripte en dos caracteres distintos en el mensaje encriptado.

Se trabaja con un alfabeto de 26 letras (A=0, B=1, ... ,Z=25).

Todas las operaciones aritméticas se realizan en la forma módulo 26, es decir que 26=0, 27=1, 28=2 etc.







Implementación
#include< conio.h >
#include < math.h >
#include < string.h >
#include < stdio.h >
#include < stdlib.h >
#include< iostream >
using namespace std;
int *euclidesExtendidoMCD(int a, int b);
int inversoMultiplicativo(int a, int z);
char *preMatriz(char *clave,char *letras,char *textCpy);
void ingresarMatriz(int d,int M[][100]);
void mostrarMatriz(int d, int M[][100]);
void multiplicarMatriz(int M[][100],int P[][100], int C[][100], int m,int p,int n);
int subMatriz(int i, int j, int M[][100],int temp[][100],int d);
int determinanteMatriz(int M[][100],int d);
void algoCifradoHill(char *text, int M[][100], int d);
void desencriHill(char *text, int M[][100], int d);
char *agrupar(char *text,char *textAgru,int d);
bool comparar(char *clave,char a,int k);
int *euclidesExtendidoMCD(int a, int b){
 
 int d,x,y;
 int x1,x2,y1,y2;
 int q,r;
 int *rpts=new int[3];
 
 if(b==0){
  d=a;
  x=1;
  y=0; 
  
  rpts[0]=d; rpts[1]=x; rpts[2]=y;
  return rpts;
 }
 x1=0; x2=1;
 y1=1; y2=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;    
 }
 //d=a;
 rpts[0]=a; rpts[1]=x2; rpts[2]=y2;
 
 return rpts;
}

int inversoMultiplicativo(int a, int z){
 
 int *resp;
 int inver;     
 
 resp=euclidesExtendidoMCD(a,z);
 
 if(resp[0]==1){
  if(resp[1]< 0)
   inver=z+resp[1];
  else if(resp[1] >0)
   inver=resp[1];    
  delete(resp);
  return inver;
 }       
 else {            
  delete(resp);
  return -1;
 }
 
}

void ingresarMatriz(int d,int M[][100]){
 
 cout< < "\n";
 for(int i=0;i< d;i++)
  for(int j=0;j< d;j++){
   do{
    
    cout< < "\t\tMatriz ["< < i+1< < "]["< < j+1< < "]: ";
    cin > >M[i][j];
    if(M[i][j]< 0 || M[i][j] >25){
     cout< < "\n\t\tDebe ingresar los numeros en el rango de 0 a 25\n";
    }
    
   }while(M[i][j]< 0 || M[i][j] >25);   
   
  }
 
}

void mostrarMatriz(int d, int M[][100]){
 
 for(int i=0;i< d;i++){
  cout< < "|";
  for(int j=0;j< d;j++)
   cout< < M[i][j]< < " ";
  cout< < "|\n";
 }
}

void multiplicarMatriz(int M[][100],int P[][100], int C[][100], int m,int p,int n){
 int s;  
 
 for (int i=0;i< m;i++){
  for(int j=0;j< n;j++){
   s=0;          
   for(int k=0;k< p;k++){
    s+=M[i][k]*P[k][j];
   }
   C[i][j]=s;
  }
 }
}

int subMatriz(int i, int j, int M[][100],int temp[][100],int d){
 
 int fil=0;
 int col=0;
 
 for(int k=0;k< d;k++){
  if(k!=i){
   col=0;
   for(int l=0;l< d;l++){
    if(l!=j){
     temp[fil][col]=M[k][l];
     col++;
    }
    
   }
   fil++;   
  }
  
 }
 return determinanteMatriz(temp,d-1);
}
int determinanteMatriz(int M[][100],int d){
 
 int temp[100][100];
 
 if(d==2){
  int deter=M[0][0]*M[1][1]-M[1][0]*M[0][1]; 
  
  return deter;
 }else{
  int deter=0;
  
  for(int j=0;j< d;j++){      
   subMatriz(0,j,M,temp,d);
   deter=deter+pow(-1,0+j)*M[0][j]*determinanteMatriz(temp,d-1);
   
  }
  
  return deter;
 }
 
}
bool comparar(char *clave,char a,int k){
 
 for(int i=0;i< k;i++){
  if(clave[i]==a)
   return false;
 }
 
 return true;
}

char *preMatriz(char *clave,char *letras,char *textCpy){
 
 int k=0,i=0; 
 bool band=true;  
 
 while(k< 25){  
  
  if(clave[k]=='j')
   clave[k]='i'; 
  
  if(clave[k]!='\0' && band==true){ 
   if(clave[k]!=' ' && clave[k] >96 && clave[k]< 123){      
    if(comparar(clave,clave[k],k)){
     textCpy[i]=clave[k];
     i++;                          
    }  
   }
  }
  else{
   if(band==true)
    k=0;
   band=false;
   if(comparar(textCpy,letras[k],i)){
    textCpy[i]=letras[k];
    i++;                          
   }
  }     
  
  k++;
 }
 textCpy[25]='\0';
 //cout< < "i: "< < i;
 return textCpy;
}

void algoCifradoHill(char *text, int M[][100], int d){
 
 char textAgru[500]; 
 
 int P[100][100],p=0;
 int C[100][100];
 int inver,deter,verfInver;
 int k=0,m=0,ini=0,tam;
 
 deter=determinanteMatriz(M,d)%26; 
 
 if(deter< 0){
  verfInver=deter+26;
  //cout< < "\n\t\tDeterminante: "< < verfInver< < "\n";
 }
 else{ 
  verfInver=deter;
  //  cout< < "\n\t\tDeterminante: "< < verfInver< < "\n";
 }
 inver=inversoMultiplicativo(verfInver,26); 
 //cout< < "\n\t\tinverso("< < verfInver< < ",26) = "< < inver< < "\n";
 
 if(deter!=0 && inver!=-1){
  strcpy(textAgru,agrupar(text,textAgru,d));
  
  tam=strlen(textAgru);
  
  cout< < "\n\t\tTexto: "< < textAgru;
  
  while(k< =tam){   
   
   if(p< d){          
    P[p][0]=textAgru[k]-97; 
    //cout< < P[p][0]< < " " ;
    p++; 
   }else{      
    multiplicarMatriz(M,P,C,d,p,1);
    for(int i=ini;i< k;i++){
     textAgru[i]=(C[m][0]%26)+97;    
     m++;
     
    }            
    ini=k+1;
    m=0;
    p=0;
    
   }  
   k++;
  }
  
  cout< < "\n\t\tTexto Encriptado: "< < textAgru;
 }else
  cout< < "\n\t\tCon la clave matrices ingresada no se puede encriptar el mensaje";
 
}

void desencriHill(char *text, int M[][100], int d){
 
 int inver,deter,verfInver; 
 int resul,tam,ini=0,p=0,k=0,m=0;
 
 int P[100][100];
 int C[100][100]; 
 int A[100][100];
 int temp[100][100];
 
 deter=determinanteMatriz(M,d)%26; 
 
 if(deter< 0){
  verfInver=deter+26;
  cout< < "\n\t\tDeterminante: "< < verfInver< < "\n";
 }
 else{ 
  verfInver=deter;
  cout< < "\n\t\tDeterminante: "< < verfInver< < "\n";
 }
 inver=inversoMultiplicativo(verfInver,26); 
 cout< < "\n\t\tinverso("< < verfInver< < ",26) = "< < inver< < "\n";
 
 if(deter!=0 && inver!=-1){
  
  for(int i = 0; i <  d; i++) 
   for(int j = 0; j <  d ;j++)               
    A[j][i] = pow(-1,i+j)*subMatriz(i,j,M,temp,d);
  
  for(int i = 0; i <  d; i++){    
   for(int j = 0; j <  d ;j++){
    resul=A[i][j]*inver;             
    if(resul< 0)
     A[i][j]=(resul%26)+26;
    else   
     A[i][j]=resul%26;
   }               
   
  } 
  tam=strlen(text); 
  
  cout< < "\n\t\tTexto: "< < text;
  
  while(k< =tam){   
   
   if(p< d){          
    P[p][0]=text[k]-97; 
    //cout< < P[p][0]< < " " ;
    p++; 
   }else{      
    multiplicarMatriz(A,P,C,d,p,1);
    for(int i=ini;i< k;i++){
     text[i]=(C[m][0]%26)+97;    
     m++;
     
    }            
    ini=k+1;
    m=0;
    p=0;
    
   }  
   k++;
  }
  
  cout< < "\n\t\tTexto Desencriptado: "< < text;
  
  
 }else
  {cout< < "\n\t\tCon la clave matrices ingresada no se puede desencriptar el mensaje";}
 cout< < endl;
 system("pause");
 
 
}
char *agrupar(char *text,char *textAgru,int d){
 
 int k=0,i=0;
 int cont=0;
 
 
 while(text[k]!='\0'){
  
  if(text[k]!=' '){
   if(cont!=d){
    textAgru[i]=text[k];
    cont++;
    i++;
   }
   else{         
    textAgru[i]=' ';
    textAgru[i+1]=text[k];
    i+=2;
    cont=1;
   }
   
  } 
  k++; 
 }
 
 while(cont< d){
  textAgru[i]='x';
  cont++;
  i++;
 }
 textAgru[i]='\0';
 
 return textAgru;
}

int main(int argc, char *argv[]) {
 char text[500];
 int M[100][100];
 int d;   
 int opcion;
 while(1)
 {
  system("cls");
  cout< < "\n\t\t\tALGORITMOS DE ENCRIPTACION HILL\n";
  cout< < "1. ENCRRIPTAR\n";
  cout< < "2. DESENCRRIPTAR\n";
  cout< < "INGRESE OPCION: ";
  cin > >opcion;
  switch(opcion)
  {
   case 1:
   {
    system("cls");
    cout< < "\n\t\t\tALGORITMOS DE ENCRIPTACION HILL - ENCRIPTACION\n";
    cout< < "\n\t\tINGRESE TEXTO: ";
    fflush(stdin);
    gets(text);
    strcpy(text,strlwr(text));
    cout< < "\n\t\tINGRESE TAMAÑO DE MATRIZ DXD: ";
    cin > >d; 
    ingresarMatriz(d,M);
    algoCifradoHill(text,M,d);
    cout< < endl;
    system("pause");
    break;
   }
   case 2:
   {
    system("cls");
    cout< < "\n\t\t\tALGORITMOS DE ENCRIPTACION HILL - DESENCRIPTACION\n";
    cout< < "\n\t\tINGRESE TEXTO: ";
    fflush(stdin);
    gets(text);
    strcpy(text,strlwr(text));
    cout< < "\n\t\tINGRESE TAMAÑO DE MATRIZ DXD: ";
    cin > >d; 
    ingresarMatriz(d,M);
    desencriHill(text,M,d);
    cout< < endl;
    system("pause");
    break; 
   }
  }
 }
 return 0;
}

sábado, 25 de julio de 2015

CIFRADO DE PLAYFAIR

El cifrado de Playfair es un ejemplo de sustitución digrámica, donde un par de letras de un texto en claro (mensaje sin codificar) se convierten en otro par distinto, para de esta forma codificar información que no deseamos sea leída.
El cifrado de Playfair trabaja con una matriz de 5x5 letras, cifrando por digramas (bloques de a dos caracteres).










IMPLEMENTACIÓN:

#include  < iostream > 
#include  < string.h > 
#include  < stdio.h > 
#include  < stdlib.h > 
#include < conio.h > 
using namespace std;

bool comparar(char *clave,char a,int k){
   
   for(int i=0;i < k;i++){
       if(clave[i]==a)
    return false;
   }
   
   return true;
}

char *preMatriz(char *clave,char *letras,char *textCpy){
 
 int k=0,i=0; 
 bool band=true;  
 
 while(k < 25){  
    
    if(clave[k]=='j')
     clave[k]='i'; 
     
    if(clave[k]!='\0' && band==true){ 
      if(clave[k]!=' ' && clave[k] > 96 && clave[k] < 123){      
      if(comparar(clave,clave[k],k)){
         textCpy[i]=clave[k];
      i++;                          
      }  
     }
    }
    else{
       if(band==true)
         k=0;
       band=false;
       if(comparar(textCpy,letras[k],i)){
          textCpy[i]=letras[k];
       i++;                          
       }
       }     
        
      k++;
 }
 textCpy[25]='\0';
 //cout <  < "i: " <  < i;
    return textCpy;
}

char *agrupar(char *text,char *textAgru){
 
 int k=0,i=0;
 int cont=0;
 
 while(text[k]!='\0'){
  
  if(text[k]=='j')
     text[k]='i';
  
  if(text[k]!=' '){
   if(cont!=2){
    textAgru[i]=text[k];
    cont++;
    i++;
   }
   else{
     if(textAgru[i-2]==textAgru[i-1]){
      textAgru[i-1]='x';
      textAgru[i]=' ';
            textAgru[i+1]=text[k-1];
            k--;
         i+=2;
         cont=1;
     } 
     else{     
         textAgru[i]=' ';
            textAgru[i+1]=text[k];
         i+=2;
         cont=1;
     }
    }     
  } 
  k++; 
 }
 //cout <  < "i: " <  < i <  < "\n";
 if(textAgru[i-2]==' '){ 
    textAgru[i]='x';
    textAgru[i+1]='\0';
    }
 else   
     textAgru[i]='\0';
     
 return textAgru;
}

void algoCifradoPlaySyFair(char *text,char *clave,char *letras){
 
 char textCpy[25];
 char textAgru[500]; 
 char matriz[5][5];
 int k=0,m=0,sum1,sum2;
 int f1,f2,c1,c2;
 bool band1=true,band2=true;
 
 strcpy(textCpy,preMatriz(clave,letras,textCpy));
 
 for(int i=0;i < 5;i++){
  for(int j=0;j < 5;j++){
   matriz[i][j]=textCpy[k];
   k++;
  }
 }
 
 strcpy(textAgru,agrupar(text,textAgru));
 
 cout <  < "\n" <  < textAgru;
 
 while(textAgru[m]!='\0'){
  
  for(int i=0;i < 5;i++){
   for(int j=0;j < 5;j++){
    if(matriz[i][j]==textAgru[m] && band1==true){     
     f1=i;
     c1=j;
     band1=false;
    }           
    if(matriz[i][j]==textAgru[m+1] && band2==true){     
     f2=i;
     c2=j;
     band2=false;
    }
   }
  }
  
  if(f1==f2){
   sum1=c1+1;
   sum2=c2+1;
   if(sum1 > 4)
      textAgru[m]=matriz[f1][0];
            else
               textAgru[m]=matriz[f1][c1+1];
               
            if(sum2 > 4)
      textAgru[m+1]=matriz[f2][0];
   else   
      textAgru[m+1]=matriz[f2][c2+1];
  }
  else if(c1==c2){
      sum1=f1+1;
      sum2=f2+1;
      
      if(sum1 > 4)
        textAgru[m]=matriz[0][c1];
      else
        textAgru[m]=matriz[f1+1][c1];
      
      if(sum2 > 4)
        textAgru[m+1]=matriz[0][c2];   
      else    
        textAgru[m+1]=matriz[f2+1][c2];   
  }else{
   textAgru[m]=matriz[f1][c2];  
            textAgru[m+1]=matriz[f2][c1];
  }
    
   m=m+3;
   band1=true;
   band2=true;
 }
 
 cout <  < "\n\n";
 for(int i=0;i < 5;i++){
  for(int j=0;j < 5;j++)
   cout <  < matriz[i][j] <  < " ";   
  cout <  < endl;
 }
 
 cout <  < "\n" <  < textAgru;
 
}

void descifradoPlaySyFair(char *text,char *clave,char *letras){
 
 char textCpy[25];
 char textAgru[500]; 
 char matriz[5][5];
 int k=0,m=0,sum1,sum2;
 int f1,f2,c1,c2;
 bool band1=true,band2=true;
 
 strcpy(textCpy,preMatriz(clave,letras,textCpy));
 
 for(int i=0;i < 5;i++){
  for(int j=0;j < 5;j++){
   matriz[i][j]=textCpy[k];
   k++;
  }
 }
 
 strcpy(textAgru,agrupar(text,textAgru));
 
 cout <  < "\n" <  < textAgru;
 
 while(textAgru[m]!='\0'){
  
  for(int i=0;i < 5;i++){
   for(int j=0;j < 5;j++){
    if(matriz[i][j]==textAgru[m] && band1==true){     
     f1=i;
     c1=j;
     band1=false;
    }           
    if(matriz[i][j]==textAgru[m+1] && band2==true){     
     f2=i;
     c2=j;
     band2=false;
    }
   }
  }
  
  if(f1==f2){
   sum1=c1-1;
   sum2=c2-1;
   if(sum1 < 0)
      textAgru[m]=matriz[f1][4];
            else
               textAgru[m]=matriz[f1][c1-1];
               
            if(sum2 < 0)
      textAgru[m+1]=matriz[f2][4];
   else   
      textAgru[m+1]=matriz[f2][c2-1];
  }
  else if(c1==c2){
      sum1=f1-1;
      sum2=f2-1;
      
      if(sum1 < 0)
        textAgru[m]=matriz[4][c1];
      else
        textAgru[m]=matriz[f1-1][c1];
      
      if(sum2 < 0)
        textAgru[m+1]=matriz[4][c2];   
      else    
        textAgru[m+1]=matriz[f2-1][c2];   
  }else{
   textAgru[m]=matriz[f1][c2];  
            textAgru[m+1]=matriz[f2][c1];
  }
    
   m=m+3;
   band1=true;
   band2=true;
 }
 
 cout <  < "\n\n";
 for(int i=0;i < 5;i++){
  for(int j=0;j < 5;j++)
   cout <  < matriz[i][j] <  < " ";   
  cout <  < endl;
 }
 
 cout <  < "\n" <  < textAgru;
 
 
 
}

int main()
{ 
 char letras[25]={'a','b','c','d','e',
                  'f','g','h','i','k',
      'l','m','n','o','p',
      'q','r','s','t','u',
      'v','w','x','y','z'}; 
 char text[500];
 char clave[250];
 int n;
 int opcion;
 cout <  < "\t\tALGORITMO PLAYFAIR";
 while(1)
 {
  system("cls");
  cout <  < "\n\t\tALGORITMO DE VERNAM\n\n";
  cout <  < "1. ENCRIPTAR\n";
  cout <  < "2. DESENCRIPTAR\n";
  cout <  < "INGRESE OPCION: ";
  cin >  > opcion;
  switch(opcion)
  {
  case 1: 
   {
    system("cls");
    cout <  < "\t\tALGORITMO PLAYFAIR - CIFRAR\n";
    cout <  < "INGRESAR TEXTO(SIN ESPACIOS): ";
    fflush(stdin);
    gets(text);
    
    cout <  < "INGRESE CLAVE: ";
    fflush(stdin);
    gets(clave);
    algoCifradoPlaySyFair(text,clave,letras);
    getch(); 
    break;
   }
  case 2:
   {
    system("cls");
    cout <  < "\t\tALGORITMO PLAYFAIR - DESCIFRAR\n";
    cout <  < "INGRESAR TEXTO(SIN ESPACIOS): ";
    fflush(stdin);
    gets(text);
    
    cout <  < "INGRESE CLAVE: ";
    fflush(stdin);
    gets(clave);
    descifradoPlaySyFair(text,clave,letras);
    getch(); 
    break;
   }
  }
 }
 system("pause");
 
}

CIFRADO DE VERNAM

El cifrado de Vernam también llamado máscara desechable es parecido al cifrado de Vigenère solo que aquí la clave es aleatoria y tan larga como el mensaje, además se debe utilizar una sola vez. Claude Shannon en su trabajo “Teoría de las comunicaciones secretas” demostró que estas características hacen que este cifrado sea perfectamente seguro ya que no hay manera de criptoanalizarlo (es matemáticamente complicado).
En este criptosistema tanto el texto plano, el texto cifrado y la clave son números modulo 2 (binario).
El método de cifrado y descifrado utilizan la función lógica XOR.

La longitud del texto (plano o cifrado) es obligatoriamente igual a la longitud de la clave.



Implementación
#include  < iostream > 
#include  < bitset > 
#include  < string.h > 
#include  < stdio.h > 
#include  < stdlib.h > 
#include < conio.h > 
using namespace std;

void algorCifraVernam(char *cadena, char *clave){
 
 char textEn[100];
 
 int tamCad,tamCla,cad,clav;
    int output[100][100];
 
 tamCad=strlen(cadena);
   tamCla=strlen(clave);
   
   strcpy(textEn,cadena);
       
    if(tamCad==tamCla){
     
  for(int i=0;i < tamCad;i++){
   for(int j=0;j < 7;j++){
    cad=(cadena[i] >  > (6-j))&1;
    clav=(clave[i] >  > (6-j))&1;
    output[i][j]=cad^clav;
   }
  }
  cout <  < "TEXTO CIFRADO: ";
  for(int i=0;i < tamCad;i++){
   for(int j=0;j < 7;j++)
    if(j==6)
    {cout <  < output[i][j];}
  }
  cout <  < "\n";
 }else
   cout <  < "LA LONGUITUD DE LA CADENA Y LA CLAVE DEBE DE SER LA MISMA";
}


void descripVernam(char *cadena, char *clave){
 
 char textEn[100];
 
 int tamCad,tamCla;
    int output[100];
 
 tamCad=strlen(cadena);
   tamCla=strlen(clave);
   
   strcpy(textEn,cadena);
       
    if(tamCad==tamCla){
     
  for(int i=0;i < tamCad;i++){      
   output[i]=cadena[i]^clave[i];
  }
  cout <  < "TEXTO DESCIFRADO: ";
  for(int i=0;i < tamCad;i++){   
    cout <  < output[i];   
  }
  cout <  < "\n";
 }else
  cout <  < "LA LONGUITUD DE LA CADENA Y LA CLAVE DEBE DE SER LA MISMA";
 
}

int main()
{
 char cadena[100];
 char clave[100];
 int opcion;
 while(1)
 {
  system("cls");
  cout <  < "\n\t\tALGORITMO DE VERNAM\n\n";
  cout <  < "1. ENCRIPTAR\n";
  cout <  < "2. DESENCRIPTAR\n";
  cout <  < "INGRESE OPCION: ";
  cin >  > opcion;
  switch(opcion)
  {
  case 1: 
   {
    system("cls");
    cout <  < "\n\t\tALGORITMO DE VERNAM  -  CIFRADO \n\n";
    cout <  < "INGRESE TEXTO: ";
    fflush(stdin);
    gets(cadena);
    
    cout <  < "INGRESE CLAVE: ";
    fflush(stdin);
    gets(clave);
    algorCifraVernam(cadena,clave);
    getch(); 
    break;
   }
  case 2:
   {
    system("cls");
    cout <  < "\n\t\tALGORITMO DE VERNAM  -  DESCIFRADO \n\n";
    cout <  < "INGRESE TEXTO: ";
    fflush(stdin);
    gets(cadena);
    cout <  < "INGRESE CLAVE: ";
    fflush(stdin);
    gets(clave);
    descripVernam(cadena,clave);
    getch(); 
    break;
   }
  }
 }
 system("pause");
}


CIFRADO DE VIGENERE

Este cifrado soluciona la debilidad del cifrado del César en que una letra se cifra siempre igual. Se usa una clave K de longitud L y se cifra carácter a carácter sumando módulo n el texto en claro con los elementos de esta clave.


Implementación:

#include  < iostream > 
#include  < cstdlib > 
#include  < string.h > 
#include < conio.h > 
using namespace std;

string alfabeto = "abcdefghijklmnopqrstuvwxyz";

void encriptardoVigenere (){
 string texto, clave, encriptar;
 cout <  < "\n\n\t INGRESE TEXTO(SIN ESPACIO): ";cin >  > texto;
 cout <  < "\n\n\t INGRESE CLAVE: ";cin >  > clave;
 
 int tamtexto = texto.size(); 
 int tamclave = clave.size(); 
 int postexto , posclave;
 if ( tamtexto  >  tamclave){
  for ( int i = 0; i  <  texto.size(); i++){
   clave += clave [i];
   //cout <  < " " <  < clave [i];
  }
  for ( int i = 0; i  <  texto.size(); i++){
  postexto = alfabeto.find(texto[i]);
  posclave = alfabeto.find(clave[i]); 
        encriptar += alfabeto[(postexto + posclave)%26];
  }
 }else {
  for ( int i = 0; i  <  texto.size(); i++){
   postexto = alfabeto.find(texto[i]);
   posclave = alfabeto.find(clave[i]); 
         encriptar += alfabeto[(postexto + posclave)%26];
  }
 }
 // mostrar texto encriptado
 cout <  < "\n\n\t TEXTO ENCRIPTADO:  ";
    for (int i = 0 ; i  <  texto.size() ; i++){
        cout <  < encriptar[i];
    } 
}

void desencriptar(){
 string texto, clave, desencriptar;
 int resultado;
 
 cout <  < "\n\n\t INGRESE TEXTO(SIN ESPACIO): ";cin >  > texto;
 cout <  < "\n\n\t INGRESE CLAVE: ";cin >  > clave;
 
 int tamtexto = texto.size(); 
 int tamclave = clave.size(); 
 int postexto , posclave;
 
 if ( tamtexto  >  tamclave){
  for ( int i = 0; i  <  texto.size(); i++){
   clave += clave [i];
   //cout <  < " " <  < clave [i];
  }
  for ( int i = 0; i  <  texto.size(); i++){
   postexto = alfabeto.find(texto[i]);
   posclave = alfabeto.find(clave[i]); 
   resultado = postexto - posclave;
   if ( resultado  <  0){
    resultado = 26 + resultado;
    desencriptar += alfabeto[resultado%26];
   }
   else{
    desencriptar += alfabeto[resultado%26];
   }         
  }
 }else {
  for ( int i = 0; i  <  texto.size(); i++){
   postexto = alfabeto.find(texto[i]);
   posclave = alfabeto.find(clave[i]); 
   resultado = postexto - posclave;
   if ( resultado  <  0){
    resultado = 26 + resultado;
    desencriptar += alfabeto[resultado%26];
   }
   else{
    desencriptar += alfabeto[resultado%26];
   }
  }
 } 
    cout <  < "\n\n\t TEXTO DESENCRIPTADO:  ";
    for (int i = 0 ; i  <  texto.size() ; i++){
        cout <  < desencriptar[i];
    }
}
int main (void)
{
     
 string alfabeto = "abcdefghijklmnopqrstuvwxyz";
 int opcion;
 cout <  < "\n\n\t\t CIFRADO DE VIGENERE";
 cout <  < endl;
 cout <  < endl;
 cout <  < "1. ENCRIPTAR ";
 cout <  < endl;
    cout <  < "2. DESENCRIPTAR";
    cout <  < endl;
    cout <  < endl;
    cout <  < "INGRESAR OPCION: ";
    cin >  > opcion;
    
    switch(opcion)
    {
     
  case 1:
  {
          
   encriptardoVigenere ();
   getch(); 
   break;
  }
  case 2:
  {
          
         desencriptar();
         getch(); 
         break;
        }
  system("pause");
 }
}