Taller de Criptografia con Algoritmos en java

Iniciado por user_en1gm4, Abril 22, 2018, 01:01:03 PM

Tema anterior - Siguiente tema

0 Miembros y 1 Visitante están viendo este tema.

Abril 22, 2018, 01:01:03 PM Ultima modificación: Junio 13, 2018, 04:16:35 PM por user_en1gm4
Hola compañer@s, hoy quiero hacer este taller ya que me gusta mucho todo este tema y quisiera compartirles algo de lo que se, se trata de un taller de criptografia con algoritmos paso a paso hechos por mi, de diferentes tipos de cifrado empezando por los clasicos hasta llegar a los actuales (en algunos todavia estoy trabajando, los mas complejos), en este taller enseñare paso a paso como codear estos algoritmos con ejemplos graficos, ademas de diversas actividades para los mas curiosos y que quieran aprender de mas.


Sugerencia saber de java (los algoritmos seran codeados en este lenguaje) y algo de estructura de datos (arrays,matrices,listas,codigo ASCII), bueno sin mas que decirles voy a comenzar.

Aca voy a colocar todos los algoritmos: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
Quiero decir algo y esque en esto de la programacion hay muchas formas de hacer algo, esta es mi forma los algortimos no estan hechos por un programador profesional ni nada, soy un estudiante todavia pero me gusta mucho esto, asi que quise compartirlo.



TALLER DE CRIPTOGRAFIA



Empecemos definiendo que es, para que se utiliza la criptografia y sus objetivos:

-  CRIPTOGRAFIA

La palabra Criptografía proviene del griego "kryptos" que significa oculto, y "graphia", que significa escritura, y su definición según el dicccionario es "Arte de escribir con clave secreta o de un modo enigmático". La Criptografía es una técnica, o más bien un conjunto de técnicas, que originalmente tratan sobre la protección o el ocultamiento de la información frente a observadores no autorizados. Es parte de un campo de estudios que trata las comunicaciones secretas,  Estas técnicas se utilizan tanto en el arte como en la ciencia y en la tecnología. Por tanto, el único objetivo de la criptografía era conseguir la confidencialidad de los mensajes, para lo cual se diseñaban sistemas de cifrado y códigos.

La criptografia es algo muy antiguo, no es algo que nace con la informatica, si no que era usada miles de años antes por egipcios, romanos,tambien en la primera y segunda guerra mundial.

Aca les dejo una buena introduccion a la criptografia si quieren saber mas a fondo y un poco de su historia, les recomiendo que revisen los links que les dejo a lo largo del taller para complementar lo que aca esta escrito.

No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Wikipedia: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta



- OBJETIVOS DE LA CRIPTOGRAFIA

En la criptografia tenemos 3 objetivos principales, es lo que se quiere conseguir despues de aplicar alguna tecnica criptografica a alguna informacion o comunicacion


       
  • Confidencialidad:
  • Es decir, garantiza que la información sea accesible únicamente a personal autorizado.
  • Integridad:
  • Grantiza que la informacion no sea modificada y se mantanga tal cual se creo
  • Autentificacion:
Es decir proporciona mecanismos que permiten verificar la identidad del comunicador, osea que quien envia el mensaje o informacion se confirme que venga de el

Nota:
No me extendere tanto explicando todo esto ya que en los link que les deje esta toda esa informacion y aun mas(en google podrian buscar criptografia y saldrian millones de resultados), el fin de este taller es entender como funcionan las tecnicas y poder codearlos



- TIPOS DE CRIPTOGRAFIA



       
  • Criptografia Simetrica:
La criptografía simétrica solo utiliza una clave para cifrar y descifrar el mensaje, que tienen que conocer el emisor y el receptor previamente. Es la comunicación de las claves entre ambos sujetos el punto débil del sistema, ya que resulta más fácil interceptar una clave que se ha transmitido sin seguridad

   
  • Criptografia Asimetrica:
Un algoritmo de criptografía asimétrica utiliza dos claves para el envío de mensajes. Las dos claves pertenecen a la persona que recibe el mensaje. Se utiliza una clave para encriptar y otra para desencriptar. La clave que se emplea para cifrar se llama clave pública y se puede entregar a cualquier persona. (De hecho hay hasta servidores de claves públicas). La magia es que si el cifrado se ha hecho con una clave pública sólo podre desencriptar con una clave distinta de la primear asociada. Es decir: dos claves matemáticamente relacionadas de manera que lo que cifras con una solo lo puedes descifrar con la otra.

   
  • Criptografia Hibrida:
es un método criptográfico que usa tanto un cifrado simétrico como un asimétrico. Emplea el cifrado de clave pública para compartir una clave para el cifrado simétrico. El mensaje que se esté enviando en el momento, se cifra usando su propia clave privada, luego el mensaje cifrado se envía al destinatario. Ya que compartir una clave simétrica no es seguro, ésta es diferente para cada sesión.


Mas informacion
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta


Bueno muchachos ya despues de entender estos conceptos y de que estamos hablando vamos a empezar con algunos algoritmos de la criptografia clasica



- CRIPTOGRAFIA CLASICA

Son las tecnicas utilizadas antiguamente por romanos, egipcios y guerras que pasaron hace muchos años y no querian que sus mensajes fueran revelados, entre estas tecnicas se encuentran:

Cifrado Cesar

Segun Wikipedia:

En criptografía, el cifrado César, también conocido como cifrado por desplazamiento, código de César o desplazamiento de César, es una de las técnicas de cifrado más simples y más usadas. Es un tipo de cifrado por sustitución en el que una letra en el texto original es reemplazada por otra letra que se encuentra un número fijo de posiciones más adelante en el alfabeto. Por ejemplo, con un desplazamiento de 3, la A sería sustituida por la D (situada 3 lugares a la derecha de la A), la B sería reemplazada por la E, etc. Este método debe su nombre a Julio César, que lo usaba para comunicarse con sus generales.



Como se ve en la imagen solo se trata de correr un caracter 3 posiciones mas adelante, bueno y ahora si empezamos a codear:

Voy a crear una Clase  main que se llame CifradoCesar, luego creare un scanner para leer por medio del teclado y luego pedire el mensaje, de esta forma:

Código: java


public class CifradoCesar {

public static void main(String[] args) {
// TODO Auto-generated method stub

System.out.println("\t   ------------------");
System.out.println("\t  | *  CIFRADO CESAR * |");
System.out.println("\t   ------------------");

//Scanner
Scanner sc = new Scanner(System.in);


System.out.println("Ingrese el Mensaje: ");
String mensaje  = sc.nextLine();
}
}




Listo, ahora voy a crear una funcion que se llame Cifrar_Cesar y me reciba por parametros un mensaje que sera tipo String, esta funcion se encarga de convertir el mensaje en un array de caracteres (char) para luego por medio el codigo ascii obtener el numero del caracter y sumarle 3, por ejemplo la letra 'a' en codigo ascci sera el numero 97 y si a ese numero le sumamos 3,  97+3 = 100;
y 100 es el codigo ascii de la letra  'd' y como se ve en la imagen anterior se corre 3 letras, y de esta manera vamos a realizar el cifrado caracter por caracter y luego lo concatenamos a un String que sera nuestra salida de la funcion o cipher (texto ya cifrado)

Tabla de CODIGO ASCII: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Código: java


public static String Cifrar_Cesar(String mensaje){
//Texto a salir (cfrado)
String cipher = "";
//Posiciones a adelantar
int adelantar = 3;

//Convertimos el mansaje en un array de caracteres
char [] letras = mensaje.toCharArray();

//Vamos por cada caracter sumandole 3
for(int i=0;i<letras.length;i++){

// de esta manera obtenemos el codigo ascii del caracter  ((int) letras[i])
// luego a ese numero le sumamos 3 ( ((int) letras[i])+ adelantar)  <- quedaria asi
// y luego convertimos ese numero en la letra a la que hace
// referencia en el codigo ascii solo casteando el numero a (char)

cipher += (char)( ((int) letras[i])+ adelantar) ;
}

//Texto cifrado
return cipher;
}




Listo ya tenemos nuestra funcion que cifra, la podre a prueba cifrando el mensaje:  Alan Mathison Turing


Y nos dio como resultado: Dodq#Pdwklvrq#Wxulqj 
que si lo revisamos nos damos cuenta que si hace lo que esperabamos,
la letra A + 3posiciones = letra D, luego la letra 'l' + 3 posiciones = letra 'o' y asi sucesivamente, listo ya tenemos nuestra funcion de cifrar.


Bueno ahora necesitamos una funcion que coja el cipher(texto cifrado) y nos devuelva nuestro mensaje normal
Para esto creare una funcion que se llamara Descifrar_Cesar y me reciba por parametro un String que sera el cipher para luego hacer casi lo anterior de la funcion cifrar pero en vez de sumarle 3 al codigo ascii le voy a restar 3 para volverlo a la posicion normal, no la comentare tanto porque hace casi lo mismo que la anterior solo que no suma sino resta posiciones

Código: java


public static String Descifrar_Cesar(String cipher){

String mensaje = "";
//Posiciones a atrasar
int adelantar = 3;
//Caracteres del mensaje
char [] letras = cipher.toCharArray();
for(int i=0;i<letras.length;i++){
mensaje += (char)( ((int) letras[i])- adelantar) ;
}
return mensaje;
}


Listo ya tenemos nuestras dos funciones de cifrar y descifrar vamos a ponerlas a prueba!, en el main  pido un mensaje y lo mando a cifrar, luego ese mensaje cifrado lo mando a descifrar y nos debe mostrar nuestro texto cifrado y nuestro texto normal luego de pasar por estas funciones, quedaria algo asi:

Código: java


public class CifradoCesar {

public static void main(String[] args) {
// TODO Auto-generated method stub

System.out.println("\t   ------------------");
System.out.println("\t  | *  CIFRADO CESAR * |");
System.out.println("\t   ------------------");

//Scanner
Scanner sc = new Scanner(System.in);


System.out.println("Ingrese el Mensaje: ");
String mensaje  = sc.nextLine();

System.out.println("\n-------------------------------");
String cipher =Cifrar_Cesar(mensaje);
System.out.println("Cifrado: "+cipher);

String descifrado = Descifrar_Cesar(cipher);
System.out.println("-------------------------------");
System.out.println("Descifrado: "+descifrado);
System.out.println("-------------------------------");

}



public static String Cifrar_Cesar(String mensaje){
//Texto a salir (cfrado)
String cipher = "";
//Posiciones a adelantar
int adelantar = 3;

//Convertimos el mansaje en un array de caracteres
char [] letras = mensaje.toCharArray();

//Vamos por cada caracter sumandole 3
for(int i=0;i<letras.length;i++){

// de esta manera obtenemos el codigo ascii del caracter
//  ((int) letras[i]) y luego a ese numero le sumamos 3
// ( ((int) letras[i])+ adelantar) <- quedaria asi
// y luego convertimos ese numero en la letra a la que hace
// referencia en el codigo ascii solo casteando el numero a (char)
cipher += (char)( ((int) letras[i])+ adelantar) ;
}
//Texto cifrado
return cipher;
}



public static String Descifrar_Cesar(String cipher){

String mensaje = "";
//Posiciones a atrasar
int adelantar = 3;
//Caracteres del mensaje
char [] letras = cipher.toCharArray();
for(int i=0;i<letras.length;i++){
mensaje += (char)( ((int) letras[i])- adelantar) ;
}
return mensaje;
}

}



y al ejecutarlo daria este resultado:


Listo ya tenemos nuestro algoritmo de Cifrado del Cesar!

EJERCICIO #1
Utilize el algoritmo para descifra este mensaje: r{>tzA-r??n-y|p|
Pero ahora en vez de correr solo 3 caracteres lo tendra que hacer corriendo 13 caracteres, igual para descifrar, suerte!




Cifrado Polibio

Se trata de un algoritmo trivial, donde cada letra del alfabeto es reemplazada por las coordenadas de su posición en un cuadrado. Es un caso particular de transposición mono-alfabética. osea tenemos una matriz llena de caracteres y vamos por cada caracter del mensaje y el cipher resultante seran las posiciones del caracter en la matriz

Link:
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Por ejemplo tenemos esta matriz llena de caracteres, (el abecedario)


Por ejemplo si queremos cifrar el texto HOLA en base a esta matriz lo que tendriamos que hacer seria ubicar la posicion de cada letra del mensaje , la letra H se encuentra en la fila 2 columna 3 entonces nuestro ciper seria 23 por ahora, luego vamos con la O que esta en la fila 3 - columna 4, nuestro cipher ahoa sera 23 33 y asi con todas las letras del mensaje en base a la posicion en que se encuentren en la matriz

HOLA = 23 34 31 11

Para que el mensaje sea correctamente cifrado, en la matriz se deben encontrar todos los caracteres que lo componten, osea en este ejemplo si nuestro mensaje hubiera llevado alguna numero no cifraria bien ya que en la matriz no hay ningun numero y asi, pero se puede hacer una matriz mas grande, para el algoritmo utilizare una de 7x7 para agregar los numeros y algunos signos

Listo sabiendo esto ahora empezaremos a codear:

Voy a crear una clase main llamada CifradoPolibio en la cual como anteriormente lo hicimos voy a pedir un mensaje:


Código: java



public class CifradoPolibio {

public static void main(String[] args) {

            System.out.println("\t   ---------------------");
System.out.println("\t  | *  CIFRADO POLIBIO * |");
System.out.println("\t   ---------------------");
Scanner sc = new Scanner(System.in);

System.out.println("Ingrese el Mensaje: ");
String mensaje  = sc.nextLine();
        }
                  }



Bueno y como este tipo de cifrado requiere una matriz voy a crear la mia, que sera de 7*7 , contendre numeros y signos, quedaria algo asi:

Código: java


public class CifradoPolibio {

public static void main(String[] args) {
// TODO Auto-generated method stub



System.out.println("\t   ---------------------");
System.out.println("\t  | *  CIFRADO POLIBIO * |");
System.out.println("\t   ---------------------");
Scanner sc = new Scanner(System.in);

System.out.println("Ingrese el Mensaje: ");
String mensaje  = sc.nextLine();

                    char [][] matris = {{'a','b','c','d','e','f','g'},
{'h','i','j','k','l','m','n'},
{'ñ','o','p','q','r','s','t'},
{'u','v','w','x','y','z','1'},
{'2','3','4','5','6','7','8'},
{'9','0','_','-',' ','.',','},
{'$','#','%','&','+','*','/'}};
                    }
             }




Listo ya tenemos nuestra matriz y en base a esta todos nuestros mensajes se van a cifrar

Bueno ahora vamos a crear una funcion que se llame Cifrar_Polibio que nos reciba por parametro un String que sera nuestro mensaje y una matriz de caracteres char [][], y en base a estos datos cifrar


Código: java


public static String [] Cifrar_Polibio(String mensaje, char [][] matris ){

//Se crea un array de el tamaño del mensaje ingresado
String [] cipher = new String [mensaje.toCharArray().length];

//Se convierte el mensaje en un array de char
char [] msj =  mensaje.toCharArray();



//Va por todas las letras del mensaje
for(int h=0;h<msj.length;h++){

//Va por todas las filas y columnas de la matriz
//Hasta encontrar el caracter
for(int i=0;i<matris.length;i++){

for(int j=0;j<matris[1].length;j++){

//Si lo encuentra
if(matris[i][j]== msj[h]){

//Guarda en nuestro array cipher las posiciones
//de el caracter i para las filas y j para las columnas
cipher[h]=Integer.toString(i)+Integer.toString(j);

//sale del ciclo apenas lo encuentra
break;
}
}
}
// Va imprimiendo el cipher (mensaje ya cifrado)
System.out.print(cipher[h]+" ");
}
//Retorna el cipher
return cipher;

}



y listo ya tendremos nuestra funcion que cifra, ahora haremos el paso inverso, vamos a cojer el cipher(texto cifrado) y como en este estan las posiciones de el caracter del mensaje en la matriz solo seria ir a la matriz y buscar en esa posicion y alla esta la letra a la que corresponde, vamos a crear una funcion que nos haga esto, la funcion recibe un cipher (texto cifrado), que sera un array de char, el mismo que la funcion cifrar retorna y una matriz de caracteres como parametros:

Código: java


public static String Descifrar_Polibio(String [] cipher,char [][] matris){

//Un array con la direccion de el caracter [fila][columna]
char [] direccion;
String mensaje ="";
//
//Vamos por todas las posiciones del cipher
for(int i=0;i<cipher.length;i++){

//Convertimos la direccion en un array de char
direccion = cipher[i].toCharArray();

// sabemos que en la posicion 0 esta la fila y en la posicion 1 esta la columna
//buscamos en la matriz el caracter que este en esa posicion y lo vamos concatenando al mensaje normal

mensaje+=matris[Character.getNumericValue( direccion[0])][Character.getNumericValue(direccion[1])];

}
//Imprime el mensaje ya descifrado
System.out.println(mensaje);

//Retorna el mensaje
return mensaje;
}



Y listo ya tendriamos nuestras dos funciones listas, mandamos a cifrar y descifrar en el main y nos quedari algo asi:
(no olviden que en java las posiciones empiezan en 0, ademas de esto cree una funcion imprimir para ver la matriz

Código: java

import java.util.Scanner;

public class CifradoPolibio {

public static void main(String[] args) {
// TODO Auto-generated method stub

char [][] matris = {{'a','b','c','d','e','f','g'},
{'h','i','j','k','l','m','n'},
{'ñ','o','p','q','r','s','t'},
{'u','v','w','x','y','z','1'},
{'2','3','4','5','6','7','8'},
{'9','0','_','-',' ','.',','},
{'$','#','%','&','+','*','/'}};

System.out.println("\t   ---------------------");
System.out.println("\t  | *  CIFRADO POLIBIO * |");
System.out.println("\t   ---------------------");
Scanner sc = new Scanner(System.in);

System.out.println("Ingrese el Mensaje: ");
String mensaje  = sc.nextLine();
System.out.println("\nMatriz");
Imprimir(matris);
System.out.print("\nCifrado: ");
String [] cipher = Cifrar_Polibio(mensaje,matris);
sc.close();
System.out.print("\nDescifrado: ");
String msj = Descifrar_Polibio(cipher,matris);



}

public static void Imprimir(char [][] matris){
for(int i=0;i<matris.length;i++){

for(int j=0;j<matris[i].length;j++){

System.out.print(matris[i][j]+" ");
}
System.out.println("");
}
}

public static String [] Cifrar_Polibio(String mensaje, char [][] matris ){

//Se crea un array de el tamaño del mensaje ingresado
String [] cipher = new String [mensaje.toCharArray().length];

//Se convierte el mensaje en un array de char
char [] msj =  mensaje.toCharArray();



//Va por todas las letras del mensaje
for(int h=0;h<msj.length;h++){

//Va por todas las filas y columnas de la matriz
//Hasta encontrar el caracter
for(int i=0;i<matris.length;i++){

for(int j=0;j<matris[1].length;j++){

//Si lo encuentra
if(matris[i][j]== msj[h]){

//Guarda en nuestro array cipher las posiciones
//de el caracter i para las filas y j para las columnas
cipher[h]=Integer.toString(i)+Integer.toString(j);

//sale del ciclo apenas lo encuentra
break;
}
}
}
// Va imprimiendo el cipher (mensaje ya cifrado)
System.out.print(cipher[h]+" ");
}
//Retorna el cipher
return cipher;

}

public static String Descifrar_Polibio(String [] cipher,char [][] matris){

//Un array con la direccion de el caracter [fila][columna]
char [] direccion;
String mensaje ="";
//
//Vamos por todas las posiciones del cipher
for(int i=0;i<cipher.length;i++){
//Convertimos la direccion en un array de char
direccion = cipher[i].toCharArray();

// sabemos que en la posicion 0 esta la fila y en la posicion 1 esta la columna
//buscamos en la matriz el caracter que este en esa posicion y lo vamos concatenando al mensaje normal

mensaje+=matris[Character.getNumericValue( direccion[0])][Character.getNumericValue(direccion[1])];

}
//Imprime el mensaje ya descifrado
System.out.println(mensaje);

//Retorna el mensaje
return mensaje;
}

}




Vamos a utilizarlo cifrando el mensaje: en1gm4 programa
(recuerden que los caracteres del mensaje deben estar en la matriz si no nunca encontrar la posicion y nos generara error)


nos da como cipher: 04 16 36 06 15 42 54 22 24 21 06 24 00 15 00
y si revisamos la posicion: fila 0 columna 4 = e , y si lo hacemos con todo el cipher nos daremos cuenta que si hace lo que queriamos, listo!

EJERCICIO #2
Utilize el algoritmo para descifra este mensaje:
00 14 06 30 16 54 03 11 00 54 04 16 02 21 16 26 24 00 24 00 25 54 14 21 25 54 23 30 04 54 01 30 25 02 00 25

En base a la matriz que se ve anteriormente en el programa, a mano!




Cifrado Playfair

Les dejare un video para que entiendan este tipo de cifrado ya que graficamente se entiende mucho mejor que si me pongo a copiar aca toda la teoria, necesito que entiendan bien como funciona para luego empezar a codearlo

Videos





Basicamente el cifrado consiste en una matriz con la que se cifra, la matriz se genera en base a la clave ya que esta se escribe en la matriz sin caracteres repetidos y luego si se termina de llenar la matriz con el resto de caracteres del abecedario sin repetir, numeros y signos si se desea

Se parte el mensaje en parejas por ejemplo HOLA quedaria HO LA y asi con todo el mensaje, luego ubicamos las dos letras en la matriz y miramos:

- Si estan en la misma fila se le suma una posicion a la columna de cada letra
- Si estan en la misma Columna se le suma una posicion a la fila de cada letra
-Si no estan ni en la misma Columna ni en la misma fila, se coloca su diagonal opuesta


Y listo sabiendo como funciona este cifrado vamos a empezar, primero voy a crear una clase main llamada CifradoPlayfair y hare lo mismo de siempre pedire un mensaje pero ahora tambien necesitaremos una clave asi que tambien la pediremos, seria algo asi:


Código: java

public class CifradoPlayfair {


public static void main(String[] args) {
// TODO Auto-generated method stub


System.out.println("\t   ---------------------");
System.out.println("\t  | *  CIFRADO PLAYFAIR * |");
System.out.println("\t   ---------------------");
Scanner sc = new Scanner(System.in);

System.out.println("Ingrese el Mensaje: ");
String mensaje  = sc.nextLine();
System.out.println("Ingrese la Clave:  ");
String clave  = sc.nextLine();
                                   }
            }


Bueno ya teniendo estos datos ahora voy a crear una funciona que se llame Cifrado_Playfair que recibe como parametro el mensaje y la clave, bueno antes de concentrarnos en esta funcion tambien eh creado unas funciones auxiliares que me ayudan a generar la matris y a generar las parejas de caracteres del mensaje

Con esta funcion genero la matriz en base a la clave:

Código: java

public static char [][] GenerarMatriz (String clave){
char [][] matris = new char [7][7];

char [] caracteresClave = clave.toCharArray();
char [] numeros = {'0','1','2','3','4','5','6','7','8','9'};
char [] letras = new char [26];
char [] signos = {'+','-','$','&',',','.',' ','_','*','%','=','?','¿'};
LinkedHashSet<Character> caracteresMatriz = new LinkedHashSet<>();



//Eliminamos las letras repetidas de a clave
//Se ingresa la clave sin caracteres repetidos a la coleccion que tendra todos los caracteres de la matris

for(int k=0;k<caracteresClave.length;k++){
caracteresMatriz.add(caracteresClave[k]);
}

//Se generan las letras del abecedario en base al codigo ASCII
for(int i=97;i<123;i++){
letras[i-97] = (char)i;
}



//Se ingresa el resto del abecedario
for(int i=0;i<letras.length;i++){
caracteresMatriz.add(letras[i]);
}

//Se ingresan los numeros
for(int i=0;i<numeros.length;i++){
caracteresMatriz.add(numeros[i]);
}

//Se ingresan los signos
for(int i=0;i<signos.length;i++){
caracteresMatriz.add(signos[i]);
}

//Se convierte el linkedhashSet en un array para luego meterlo en la matriz
int cont;
char [] arrayTemporal = new char [caracteresMatriz.size()];
cont=0;
for(char caracter:caracteresMatriz){
arrayTemporal[cont]=caracter;
cont++;
}



//Se ingresan a la matriz todos los caracteres (con esto tendriamos nuestra matriz lista)
cont=0;
for(int i=0;i<matris.length;i++){
for(int j=0;j<matris[0].length;j++){
matris[i][j]=arrayTemporal[cont];
cont++;
}

}

return matris;
}



y Listo con esta funcion ya generamos nuestra matriz en base a la clave, ahora necesitamos una funcion que nos forme cadenas de caracteres, si la cadena tiene un tamaño impar se le agrega el caracter 'x' al final para que sea par y tambien sabiendo que si hay dos caractere repetidos coloque una x en la mitad, por ejemplo:
LLAVE -> LXLAVE 
para que en el momento de cifrar no queden cifras iguales pegadas y pues un sabrian que es una letra que se repite como la ll o la rr algo asi.

Esta funcion recibe por parametro el mensaje y nos devuelve una matris de parejas de caracteres con la anterior regla, una salvedad, en los videos dice que al mensaje se le deben eliminar los espacios, yo en la matriz  ingrese en caracter espacio para no tener que hacer esto y que los mensajes se descifren igual como el original:

Código: java

public static char [][] GenerarParejas(String mensaje){

int tam = mensaje.length();

//Se revisa que no alla caracteres repetidos consecutivamente como "llave"
//tendria que queda lxlave

char [] revision= mensaje.toCharArray();
ArrayList<Character> arrayRevision = new ArrayList<>();
for(int i=0;i<mensaje.length();i++){
arrayRevision.add(revision[i]);

if(i+1<revision.length){
if(revision[i]==revision[i+1]){
arrayRevision.add('x');

}
}
}

//Revisamos que el mensaje quede de un tamaño par si no es asi agregamos x al final para volverlo par
if(arrayRevision.size()%2!=0){
arrayRevision.add('x');
}


//Se forma una matris de 2 columnas para las parejas de caracteres
char [][] parejaCaracteres= new char [arrayRevision.size()/2][2];
int cont =0;
for(int i=0;i<parejaCaracteres.length;i++){
for(int j=0;j<parejaCaracteres[1].length;j++){
parejaCaracteres[i][j]=arrayRevision.get(cont);
cont++;
}
}

return parejaCaracteres;
}


Listo ya tenemos dos funciones listas, pero ahora vamos a necesitar ayuda de una tercera funcion que se va a encargar de darme la posicion  de un caracter en la matriz para poder aplicar las reglas de que si esta en la misma fila o columna... etc
Bueno la funcion me recibe como parametros un caracter que sera en que vamos a buscar y una matriz en la cual vamos a buscar el caracter, quedaria algo asi:

Código: java


public static int[] ObtenerPosicionCaracter(char caracter,char [][] matris){

int [] direccion = new int [2];


for(int i =0;i<matris.length;i++ ){

for(int j=0;j<matris[i].length;j++){

if(caracter == matris[i][j]){
//fila
                                          direccion[0]=i;
                                           //columna
direccion[1]=j;
}
}

}

return direccion;

}


y Listo ya tenemos nuestras funciones listas para utilizar en nuestra funcion de cifrar, que nos recibe un mensaje y una clave como parametros, genera la matriz en base a la clave, genera las parejas de caracteres y va por cada pareja de caracteres aplicando las reglas, quedaria algo asi:

Código: java

public static String Cifrado_Playfair(String mensaje,String clave){

//Se genera la matriz
char [][] matris = GenerarMatriz(clave);
//Se generan las parejas de caracteres
char [][] parejaCaracteres = GenerarParejas(mensaje);

System.out.println("\n \t Matriz");
//Imprimimos la matriz con la misma funcion que hemos utilizado
//en todo el taller
Imprimir(matris);

//Se imprimen las parejas de caracteres
System.out.println("\n \t Parejas de caracteres");
Imprimir(parejaCaracteres);
String cipher = "";

//Los array de direcciones de las dos letras
int [] direcciones ;
int [] direcciones2;
int columna =0;
//Se va por todas las parejas de caracteres
for(int i=0;i<parejaCaracteres.length;i++){


// Se manda a obtener las posiciones de los caracteres
direcciones= ObtenerPosicionCaracter(parejaCaracteres[i][columna],matris);
columna++;
direcciones2= ObtenerPosicionCaracter(parejaCaracteres[i][columna],matris);


if(columna==1){
columna=0;
}

// Se guardan en variables para asi comparar las reglas
int fila1= direcciones[0];
int columna1= direcciones[1];

int fila2= direcciones2[0];
int columna2= direcciones2[1];


// Si estan en la misma fila se le suma +1 a la columna
int fTemporal;
if(fila1==fila2){
fTemporal= columna1+1;
if(fTemporal==matris.length){
fTemporal=0;
}

cipher+=matris[fila1][fTemporal];


fTemporal = columna2+1;
if(fTemporal==matris.length){
fTemporal=0;
}

cipher+=matris[fila2][fTemporal];
}


// si estan en la misma columna se le suma +1 a la fila
int cTemporal;
if(columna1==columna2){

cTemporal = fila1+1;

if(cTemporal == matris.length){
cTemporal=0;
}

cipher+= matris[cTemporal][columna1];

cTemporal = fila2+1;

if(cTemporal == matris.length){
cTemporal=0;
}

cipher+= matris[cTemporal][columna2];


}

// si no cumple ninguna de las anteriores
// se coloca la diagonal opuesta, se invierten las columnas

if(fila1!=fila2 & columna1!=columna2){

cipher+=matris[fila1][columna2];
cipher+=matris[fila2][columna1];


}
}

// se retorna el cipher
return cipher;
}


Y listo ya tendriamos nuestra funcion de cifrar lista!, ahora vamos a programar nuestra funcion de descifrar que hace casi lo mismo que la anterior pero de para atras xd, esta funcion nos recibe como parametros el mensaje y la clave, quedari algo asi


Código: java


public static String Descifrado_Playfair(String cipher,String clave){

String mensaje ="";

char [][] matris= GenerarMatriz(clave);
char [][] parejas = GenerarParejas(cipher);

int [] direcciones;
int [] direcciones2;

int columnas=0;
for(int i=0;i<parejas.length;i++){


direcciones= ObtenerPosicionCaracter(parejas[i][columnas],matris);
columnas++;


int fila1= direcciones[0];
int columna1= direcciones[1];


direcciones2= ObtenerPosicionCaracter(parejas[i][columnas],matris);
if(columnas==1){columnas=0;}

int fila2= direcciones2[0];
int columna2= direcciones2[1];

//Filas iguales ya no se suma , si no que ahora se resta -1 a la columna
int fTemporal;
if(fila1==fila2){
fTemporal= columna1-1;
if(fTemporal<0){
fTemporal=matris.length-1;
}

mensaje+=matris[fila1][fTemporal];


fTemporal = columna2-1;
if(fTemporal<0){
fTemporal=matris.length-1;
}

mensaje+=matris[fila2][fTemporal];
}


int cTemporal;
//Columnas iguales ya no se suma , si no que ahora se resta -1 a la fila

if(columna1==columna2){

cTemporal = fila1-1;

if(cTemporal<0){
cTemporal=matris.length-1;
}

mensaje+= matris[cTemporal][columna1];

cTemporal = fila2-1;

if(cTemporal<0){
cTemporal=matris.length-1;
}

mensaje+= matris[cTemporal][columna2];


}

//Si no se cumple ninguna se coloca la diagonal opuesta, esto no cambia
if(fila1!=fila2 & columna1!=columna2){

mensaje+=matris[fila1][columna2];
mensaje+=matris[fila2][columna1];

}

}

return mensaje;
}






Aca la funcion imprimir por si les genera error :v, es una simple funcion que me imprime una matriz:

Código: java

public static void Imprimir(char [][] matris){
for(int i=0;i<matris.length;i++){
for(int j=0;j<matris[i].length;j++){
System.out.print(matris[i][j]+" ");

}
System.out.println("");

}
}


Y bueno ya tendriamos nuestra funcion de cifrado y descifrado compañer@s!
el programa completo quedaria algo asi:

Código: java

import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.Scanner;

public class CifradoPlayfair {


public static void main(String[] args) {
// TODO Auto-generated method stub


System.out.println("\t   ---------------------");
System.out.println("\t  | *  CIFRADO PLAYFAIR * |");
System.out.println("\t   ---------------------");
Scanner sc = new Scanner(System.in);

System.out.println("Ingrese el Mensaje: ");
String mensaje  = sc.nextLine();
System.out.println("Ingrese la Clave:  ");
String clave  = sc.nextLine();


String cipher = Cifrado_Playfair(mensaje,clave);
String mensaje2 = Descifrado_Playfair(cipher,clave);

System.out.println("\nCipher: "+cipher);
System.out.println("Mensaje descifrado: "+mensaje2);

}




public static String Descifrado_Playfair(String cipher,String clave){

String mensaje ="";

char [][] matris= GenerarMatriz(clave);
char [][] parejas = GenerarParejas(cipher);

int [] direcciones;
int [] direcciones2;

int columnas=0;
for(int i=0;i<parejas.length;i++){


direcciones= ObtenerPosicionCaracter(parejas[i][columnas],matris);
columnas++;


int fila1= direcciones[0];
int columna1= direcciones[1];


direcciones2= ObtenerPosicionCaracter(parejas[i][columnas],matris);
if(columnas==1){columnas=0;}

int fila2= direcciones2[0];
int columna2= direcciones2[1];

//Filas iguales ya no se suma , si no que ahora se resta -1 a la columna
int fTemporal;
if(fila1==fila2){
fTemporal= columna1-1;
if(fTemporal<0){
fTemporal=matris.length-1;
}

mensaje+=matris[fila1][fTemporal];


fTemporal = columna2-1;
if(fTemporal<0){
fTemporal=matris.length-1;
}

mensaje+=matris[fila2][fTemporal];
}


int cTemporal;
//Columnas iguales ya no se suma , si no que ahora se resta -1 a la fila

if(columna1==columna2){

cTemporal = fila1-1;

if(cTemporal<0){
cTemporal=matris.length-1;
}

mensaje+= matris[cTemporal][columna1];

cTemporal = fila2-1;

if(cTemporal<0){
cTemporal=matris.length-1;
}

mensaje+= matris[cTemporal][columna2];


}

//Si no se cumple ninguna se coloca la diagonal opuesta, esto no cambia
if(fila1!=fila2 & columna1!=columna2){

mensaje+=matris[fila1][columna2];
mensaje+=matris[fila2][columna1];

}

}

return mensaje;
}



public static String Cifrado_Playfair(String mensaje,String clave){

//Se genera la matriz
char [][] matris = GenerarMatriz(clave);
//Se generan las parejas de caracteres
char [][] parejaCaracteres = GenerarParejas(mensaje);

System.out.println("\n \t Matriz");
//Imprimimos la matriz con la misma funcion que hemos utilizado
//en todo el taller
Imprimir(matris);

//Se imprimen las parejas de caracteres
System.out.println("\n \t Parejas de caracteres");
Imprimir(parejaCaracteres);
String cipher = "";

//Los array de direcciones de las dos letras
int [] direcciones ;
int [] direcciones2;
int columna =0;
//Se va por todas las parejas de caracteres
for(int i=0;i<parejaCaracteres.length;i++){


// Se manda a obtener las posiciones de los caracteres
direcciones= ObtenerPosicionCaracter(parejaCaracteres[i][columna],matris);
columna++;
direcciones2= ObtenerPosicionCaracter(parejaCaracteres[i][columna],matris);


if(columna==1){
columna=0;
}

// Se guardan en variables para asi comparar las reglas
int fila1= direcciones[0];
int columna1= direcciones[1];

int fila2= direcciones2[0];
int columna2= direcciones2[1];


// Si estan en la misma fila se le suma +1 a la columna
int fTemporal;
if(fila1==fila2){
fTemporal= columna1+1;
if(fTemporal==matris.length){
fTemporal=0;
}

cipher+=matris[fila1][fTemporal];


fTemporal = columna2+1;
if(fTemporal==matris.length){
fTemporal=0;
}

cipher+=matris[fila2][fTemporal];
}


// si estan en la misma columna se le suma +1 a la fila
int cTemporal;
if(columna1==columna2){

cTemporal = fila1+1;

if(cTemporal == matris.length){
cTemporal=0;
}

cipher+= matris[cTemporal][columna1];

cTemporal = fila2+1;

if(cTemporal == matris.length){
cTemporal=0;
}

cipher+= matris[cTemporal][columna2];


}

// si no cumple ninguna de las anteriores
// se coloca la diagonal opuesta, se invierten las columnas

if(fila1!=fila2 & columna1!=columna2){

cipher+=matris[fila1][columna2];
cipher+=matris[fila2][columna1];


}
}

// se retorna el cipher
return cipher;
}


public static int[] ObtenerPosicionCaracter(char caracter,char [][] matris){

int [] direccion = new int [2];


for(int i =0;i<matris.length;i++ ){

for(int j=0;j<matris[i].length;j++){

if(caracter == matris[i][j]){
direccion[0]=i;
direccion[1]=j;
}
}

}

return direccion;

}

public static char [][] GenerarParejas(String mensaje){

int tam = mensaje.length();

//Se revisa que no alla caracteres repetidos consecutivamente como "llave"
//tendria que queda lxlave

char [] revision= mensaje.toCharArray();
ArrayList<Character> arrayRevision = new ArrayList<>();
for(int i=0;i<mensaje.length();i++){
arrayRevision.add(revision[i]);

if(i+1<revision.length){
if(revision[i]==revision[i+1]){
arrayRevision.add('x');

}
}
}

//Revisamos que el mensaje quede de un tamaño par si no es asi agregamos x al final para volverlo par
if(arrayRevision.size()%2!=0){
arrayRevision.add('x');
}


//Se forma una matris de 2 columnas para las parejas de caracteres
char [][] parejaCaracteres= new char [arrayRevision.size()/2][2];
int cont =0;
for(int i=0;i<parejaCaracteres.length;i++){
for(int j=0;j<parejaCaracteres[1].length;j++){
parejaCaracteres[i][j]=arrayRevision.get(cont);
cont++;
}
}

return parejaCaracteres;
}




public static char [][] GenerarMatriz (String clave){
char [][] matris = new char [7][7];

char [] caracteresClave = clave.toCharArray();
char [] numeros = {'0','1','2','3','4','5','6','7','8','9'};
char [] letras = new char [26];
char [] signos = {'+','-','$','&',',','.',' ','_','*','%','=','?','¿'};
LinkedHashSet<Character> caracteresMatriz = new LinkedHashSet<>();



//Eliminamos las letras repetidas de a clave
//Se ingresa la clave sin caracteres repetidos a la coleccion que tendra todos los caracteres de la matris

for(int k=0;k<caracteresClave.length;k++){
caracteresMatriz.add(caracteresClave[k]);
}

//Se generan las letras del abecedario en base al codigo ASCII
for(int i=97;i<123;i++){
letras[i-97] = (char)i;
}



//Se ingresa el resto del abecedario
for(int i=0;i<letras.length;i++){
caracteresMatriz.add(letras[i]);
}

//Se ingresan los numeros
for(int i=0;i<numeros.length;i++){
caracteresMatriz.add(numeros[i]);
}

//Se ingresan los signos
for(int i=0;i<signos.length;i++){
caracteresMatriz.add(signos[i]);
}

//Se convierte el linkedhashSet en un array para luego meterlo en la matriz
int cont;
char [] arrayTemporal = new char [caracteresMatriz.size()];
cont=0;
for(char caracter:caracteresMatriz){
arrayTemporal[cont]=caracter;
cont++;
}



//Se ingresan a la matriz todos los caracteres (con esto tendriamos nuestra matriz lista)
cont=0;
for(int i=0;i<matris.length;i++){
for(int j=0;j<matris[0].length;j++){
matris[i][j]=arrayTemporal[cont];
cont++;
}

}

return matris;
}

public static void Imprimir(char [][] matris){
for(int i=0;i<matris.length;i++){
for(int j=0;j<matris[i].length;j++){
System.out.print(matris[i][j]+" ");

}
System.out.println("");

}
}



}





Listo ahora lo pondre a funcionar con el mensaje: colombia tierra querida
y con la clave:  user_$
(recuerden que los caracteres del mensaje deben estar en la matriz, para este taller no utilizare nada de mayusculas ni simbolos raros)



y me da como resultado:

Cipher: hkmpjfpis1da_w_u.tsrafie
Mensaje descifrado: colombia tierxra querida

queda tierxra porque le pusimos la regla de que en las repetidas colocara una x en la mitad recuerden,

Y listo ya tendriamos otro algoritmo listo!

EJERCICIO #e
Utilize el algoritmo para descifrar este mensaje:
vc4kb2b1sk%kpsebk_nx1cqv

Esta es la clave: en1gm4





Cifrado XOR


Bueno si han llegado hasta aca ya saben masomenos como funciona todo ese mundo de la criptografia, mueva alla, corrase tantos puestos y asi, ahora vamos a implementar otro algoritmo de cifrado pero esta vez utilizando una compuerta logica XOR

primero que todo tenemos que saber que es una compuerta logica XOR y antes de eso tener conceptos de numeros binarios ya que estas compuertas se les aplican a los binarios,

sabemos que toda la informacion en nuestra computadora por debajo al final no son las que 1 y 0;

Les dejare esta guia para que aprendan que es un bit y un byte, los que ya saben la pueden obviar

No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Bueno ya sabiendo esto que 1 byte representa 8 bits y lo demas vamos a estudiar que es una compuerta logica, para lo cual les dejo aca la informacion, no la colocare aca porque seria nada mas copiar y pegar y ps para que.

CompuertaXOR

No tienes permitido ver los links. Registrarse o Entrar a mi cuenta (pueden buscar informacion adicional si no quedo muy claro es importante que sepan como funciona)

bueno despues de saber como funciona esta compuerta tenemos esta tabla de verdad que nos ayuda a entender mejor:


Bueno ya sabiendo esto y como funciona ahora si vamos a proceder a codear el algoritmo:

Primero debemos saber que un caracter es representado por un byte, osea 8 bits que al sumarlos por medio de codigo binario nos dara el codigo ascii del caracter

lean esto para que entiendan como funciona el cifrado xor:
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta


por cuestiones de tiempo no explicare este algoritmo paso a paso si no que mostrare su funcionamiento, basicamente lo que hace es convertir el mensaje en un arreglo de caracteres, obtiene el codigo binario de ese caracter, luego convierte la clave en un arreglo de caracter y obtiene el binario de cada caracter y le aplica una compuerta XOR a estos dos binarios y para descrifrar hace lo mismo con el mensaje cifrado y la clave

Código: java

import java.util.Scanner;

public class CifradoXOR {


public static void main(String[] args) {
// TODO Auto-generated method stub

Scanner sc = new Scanner(System.in);
System.out.println("\t   ------------------");
System.out.println("\t  | *  CIFRADO XOR * |");
System.out.println("\t   ------------------");

System.out.println("Ingrese el Mensaje: ");
String mensaje  = sc.nextLine();
System.out.println("Ingrese clave");
String clave = sc.nextLine();

//Se convierte el mensaje a array de binarios
String [] mensajeB = TextoABinario(mensaje);
String [] claveB = TextoABinario(clave);


System.out.println("");
System.out.println("Mensaje: "+mensaje);
System.out.println("Clave: "+clave);
System.out.println("");

sc.close();
System.out.println("-------------------------------------------------------");
System.out.println("\t\t* Cifrando *");
System.out.println("-------------------------------------------------------");

//Se manda a cifrar
String [] resultado = Cifrado_Descifrado_XOR(mensajeB,claveB);


Imprimir(mensajeB);

System.out.print(": <-- bytes del mensaje");

System.out.println("");

Imprimir(claveB);
System.out.print(": <-- bytes de clave");

System.out.println("\n-------------------------------------------------------");

Imprimir(resultado);
System.out.print(": <-- bytes de cipher");

System.out.println("\n-------------------------------------------------------");
System.out.print(" - Mensaje Cifrado: ");
System.out.print(BinarioATexto(resultado));
System.out.println("\n-------------------------------------------------------");
System.out.println("\t\t* Descifrando *");
System.out.println("-------------------------------------------------------");

//Se manda a descifrar;
String[] resultado2 = Cifrado_Descifrado_XOR(resultado,claveB);


Imprimir(resultado);
System.out.print(": <-- bytes del cipher");

System.out.println("");
Imprimir(claveB);

System.out.print(": <-- bytes de clave");
System.out.println("\n-------------------------------------------------------");

Imprimir(resultado2);
System.out.println(": <-- bytes del mensaje desencriptado");
System.out.println("\n-------------------------------------------------------");
System.out.print(" - Mensaje Descrifrado: ");
System.out.print(BinarioATexto(resultado2));
System.out.println("\n-------------------------------------------------------");
}

public static String CompuertaXOR (String binario1 , String binario2){

char [] operando1 = binario1.toCharArray();
char [] operando2 = binario2.toCharArray();
char [] r =new char [operando1.length];

for(int i=0;i<operando1.length ;i++){


if(operando1[i]!=operando2[i]){
r [i]='1';
}else {
r [i]= '0';
}
}

String re="";
for(int j=0;j<r.length;j++){
re+=r[j];
}

return re;
}

public static String [] Cifrado_Descifrado_XOR (String [] mensaje,String [] clave){

String [] resultado = new String [mensaje.length];
int puntero=0;

for(int i =0 ;i<mensaje.length;i++){

if(puntero>=clave.length){
puntero =0;
}
resultado[i]= CompuertaXOR(mensaje[i],clave[puntero]);

puntero++;
}

return resultado;
}


public static String [] TextoABinario(String texto){

char caracter;
int codigoASCII;
String binario;
String [] binarios = new String [texto.length()];

for (int i=0;i<texto.length();i++){

caracter = texto.charAt(i);
codigoASCII = (int) caracter;

binario = "";


for(int j=7;j>=0;j--){
if(codigoASCII>=Math.pow(2, j)){
codigoASCII-=Math.pow(2,j);
binario +="1";
}else{
binario+="0";
}
}

binarios[i]= binario.toString();


}
return binarios;
}


public static String BinarioATexto(String [] binarios){
String texto="";

for(int j=0;j<binarios.length;j++){
char [] bin = binarios[j].toCharArray();

int decimal =0;

int contador=0;
for(int i=bin.length-1;i>-1;i--){

if(bin[contador]=='1'){
decimal+=Math.pow(2, i);
}

contador++;
}

texto+= (char) decimal;

}

return texto;
}

public static void Imprimir(String [] arreglo){

for(int i=0;i<arreglo.length;i++){
System.out.print(arreglo[i]+" ");
}
}


}


Lo pobrare con el mensaje: Colombia
y la clave: hacking


me da como cipher: + 
y luego de descifrar: Colombia


Bueno amigos esto es todo por hoy, aca no acaba este post seguire agregando algoritmos mas complejos con el paso del tiempo, espero les sirva de algo, ami me sirvio para profundizar mis conocimientos, me gusta todo esto de la criptografia y pues si esto lo ve algun programador lo podria utilizar en sus desarrollos para mejorar su seguridad, un saludo desde Colombia!


Muy bueno el post, me gusta mucho el tema y la explicación está muy bien, saludos.

Enviado desde mi XT1034 mediante Tapatalk


Espectacular! Muy bien explicado y detallado. Me encantó, felicitaciones!

Saludos y buena semana, NERV0.
"Ciertos programas informáticos son el reflejo del ego académico del pelotudo que los desarrolla"

Muy buen post aunque no lo segui en java sino en C me sirvio muchisimo para entender <3