Autor
|
Tema: Sistema de cifrado por lote de texto plano (Leído 13,020 veces)
|
JoseluCross
Desconectado
Mensajes: 33
Conoceréis la Verdad, y la Verdad os hará libres
|
Hola a todos, un amigo y yo hemos estado trasteando un poco con C y hemos creado un cifrado algo simplón y queremos saber como de fuerte es. Os comento un poco como funciona. Se mete un texto de entrada y uan contraseña y en la salida cada caracter de la entrada se sumará al caracter correspondiente de la contraseña siguiendo este esquema, tanto para el cifrado como el descifrado. /* *Title: crypt *Description: It de/encrypt strings *@param pass[]: string which we use like password *@param text[]: string which we will encrypt *@param x: false = encrypt, true = decrypt *@param name[]: name of output *@return text_length: text length */ void crypt(char pass[], char text[], bool x, char name[]) { int pass_length; int text_length; int passPosition = 0; //Relative position in pass[] int textPosition = 0; //Relative position in text[] pass_length = length(pass); text_length = length(text); int sol; //output character
FILE *nom;
nom = fopen(name, "w");
for(textPosition = 0; textPosition < text_length; textPosition++) { if(passPosition == pass_length) { passPosition = 0; } if(x == false) { sol = text[textPosition] + pass[passPosition]; while(sol > 126) { sol -= 94; } } else { sol = text[textPosition] - pass[passPosition]; while(sol < 32) { sol += 94; } } passPosition++; fputc(sol, nom); } fclose(nom); } Además tiene la opción de generar texto aleatorio tras la salida para meter datos que no forman parte del texto original y creemos que permite una barrera contra un ataque por estadistica de palabras. Todo el código está en https://github.com/JoseluCross/cryptoJKA/tree/master/cryptojkaQueremos saber si es seguro, o al menos, cuan seguro es. Muchas gracias
|
|
« Última modificación: 29 Marzo 2016, 18:54 pm por JoseluCross »
|
En línea
|
No hay problema sin solución, solo personas que no quieren resolverlo.
|
|
|
AlbertoBSD
Programador y
Moderador Global
Desconectado
Mensajes: 3.705
🏴 Libertad!!!!!
|
Practico el ejemplo, para fines de aprendizaje sobre sistemas de cifrados es buen trabajo, aun que realmente seguro no es.
Lo de agregar texto random suena bien, sin embargo la seguridad atravez de la oscuridad no estan segura.
Aun asi buen ejemplo para fines practicos.
|
|
|
En línea
|
|
|
|
JoseluCross
Desconectado
Mensajes: 33
Conoceréis la Verdad, y la Verdad os hará libres
|
Muchas gracias por tu comentario. ¿Como sería el modo para descifrar el contenido cifrado sin la clave correcta? Me interesa mucho el tema pero estoy algo verde. Muchas gracias.
|
|
|
En línea
|
No hay problema sin solución, solo personas que no quieren resolverlo.
|
|
|
AlbertoBSD
Programador y
Moderador Global
Desconectado
Mensajes: 3.705
🏴 Libertad!!!!!
|
Como tu lo comentas un ataque por estadistica podria arrojar algo de luz sobre la distribución / frecuencia de los datos. #include<stdio.h> #include<string.h> int main() { char *pass = "HolaMundo"; char *text = "QWERT456Y76U76I7OP6A756S7D567F6G7H56J7K67L6Ñ7Z56X7C567V65B7N65M7q56w2e3r2t41213yuiopasdfghjklzxcugjh877yvbty7t6645r311nm"; int x = 1; char *name = "salida.txt"; crypt(pass,text,x,name); return 0; }
Hice este codigo para testear tu algoritmo, deja checo la salida y la analizo. Cambie los length por strlen y cambie los bool por int para podrelo compilar sin errores, no se que compilador estes usando, en fin con los cambios que le hice funciona bien. Esta fue la salida: gF7Oe{%0HM%G4G2'I?L0)2G<'>$L&83X 8/%`&=3H5&y<MI'3i 3/%ME(2S >0$c&c2G`"_"*!f1By!-h-Xamr\T`V Y]i-aSoV"W*4Hbf\c1&f3G{%l"G `j Saludos!
|
|
|
En línea
|
|
|
|
JoseluCross
Desconectado
Mensajes: 33
Conoceréis la Verdad, y la Verdad os hará libres
|
Yo uso gcc, la funcion lenght es una función que implementé en el código. El código completo es Del data.h //Here all constant are defined
#define MAX_TEXT 1048576 #define MAX_PASS 64 #define VERSION "0.4.2" del main.c /*Title: cryptojka *Descripton: cryptation character by character *Autor: José Luis Garrido Labrador (JoseluCross) and Kevin Puertas Ruiz (Kprkpr) *Version: 0.4.2 - mar/16 */ #include <stdio.h> #include <stdbool.h> #include <string.h> #include <stdlib.h> #include "data.h"
#include "methods.c"
int clean_stdin(void); void crypt(char[], char[], bool, char[]); int length(char[]);
int main(int argc, char *argv[]) { bool state; //false when encrypt, true when decrypt bool ran = false; //false: not random generation, true: random generation bool fil; //false: not file, true, with file bool cond = false; //If false = not argument int cant = 0; //number of characters in random generation char text[MAX_TEXT] = "text"; //imput character char pass[MAX_PASS] = "pass"; //Imput pass FILE *in; //Input file char out[35] = "crypt.out"; //output file
//Flags options int i; for(i = 0; i < argc; i++) { if(strcmp(argv[i], "-e") == 0) { state = false; cond = true; } else if(strcmp(argv[i], "-d") == 0) { state = true; cond = true; } else if(strcmp(argv[i], "-f") == 0) { in = fopen(argv[i + 1], "r"); fil = true; cond = true; } else if(strcmp(argv[i], "-o") == 0) { strcpy(out, argv[i + 1]); cond = true; } else if(strcmp(argv[i], "-p") == 0) { strcpy(pass, argv[i + 1]); cond = true; } else if(strcmp(argv[i], "-t") == 0) { strcpy(text, argv[i + 1]); fil = false; cond = true; } else if(strcmp(argv[i], "-r") == 0) { ran = true; cant = atoi(argv[i + 1]); cond = true; } else if(strcmp(argv[i], "--version") == 0 || strcmp(argv[i], "-v") == 0) { printf("cryptoJKA, version: %s\n\n", VERSION); return 0; } else if(strcmp(argv[i], "-h") == 0) { helpbox(); //In methods.c return 0; } }
if(cond == false) { printf("No option specified\n"); helpbox(); return 0; }
if(state == false) { if(fil == false) { crypt(pass, text, false, out); } else { for(i = 0; feof(in) == 0; i++) { text[i] = fgetc(in); } for(i = 0; i < length(text); i++) { if(text[i] == '\n') { text[i] = ' '; } } crypt(pass, text, false, out); } if(ran == true) { rangen(cant, out); //In methods.c } } else { if(fil == false) { crypt(pass, text, true, out); } else { for(i = 0; feof(in) == 0; i++) { text[i] = fgetc(in); }
} crypt(pass, text, true, out); }
printf("\n"); showFile(out, MAX_TEXT);
return 0; }
/* *Title: crypt *Description: It de/encrypt strings *@param pass[]: string which we use like password *@param text[]: string which we will encrypt *@param x: false = encrypt, true = decrypt *@param name[]: name of output *@return text_length: text length */ void crypt(char pass[], char text[], bool x, char name[]) { int pass_length; int text_length; int passPosition = 0; //Relative position in pass[] int textPosition = 0; //Relative position in text[] pass_length = length(pass); text_length = length(text); int sol; //output character
FILE *nom;
nom = fopen(name, "w");
for(textPosition = 0; textPosition < text_length; textPosition++) { if(passPosition == pass_length) { passPosition = 0; } if(x == false) { sol = text[textPosition] + pass[passPosition]; while(sol > 126) { sol -= 94; } } else { sol = text[textPosition] - pass[passPosition]; while(sol < 32) { sol += 94; } } passPosition++; fputc(sol, nom); } fclose(nom); }
/* *Title: length *Description: It count logic string length *@param l[]: string *@return m: lenght */ int length(char l[]) { int m = 0; while(l[m] != '\0') { m++; } return m; } y del methods.c es #include "data.h"
/* *Title: showFile *Description: Print in screen a file *@param n[]:filename *@param tam: length of file */ void showFile(char n[],int tam){ char f[tam];//output string
FILE *show; show = fopen(n, "r"); fgets(f,tam,show); printf("%s\n",f); }
/* *Title: helpbox *Description: Show the help menu */ void helpbox(){ printf("\n"); printf("\tcryptoJKA from JKA Network - Version: %s\n", VERSION); printf("\n"); printf("\tThe text must be between ASCII 32 and ASCII 125\n\n"); printf("\tOptions:\n"); printf("\t -f [file_name],\tinput file\n"); printf("\t -o [file_name],\toutput file (default : crypt.out)\n"); printf("\t -p [text],\t\tpassword (default: pass)\n"); printf("\t -t [text],\t\ttext (default: text)\n\t\t\t\t\tIf you put -f and -t, text have preference\n"); printf("\t -e,\t\t\tencrypt mode\n"); printf("\t -d,\t\t\tdecrypt mode\n"); printf("\t -r [number],\t\twith random generation [number of character]\n"); printf("\t -h,\t\t\tshow this box\n"); printf("\t -v, --version,\t\tshow version\n\n"); printf("\t Examples:\n\n"); printf("\t\tcryptojka -e -t \"Example text\" -p password -o file_name -r 600\n"); printf("\t\tcryptojka -d -f file_name -p password\n\n"); }
/* *Title: random *Description: It generates random text between ASCII 32 and 126 *@param tam: max length of string *@param name[]: output name */ void rangen(int tam, char name[]){ FILE *out_text;
out_text = fopen(name, "a");
int p;//Generated num int m;//Relative position for(m=0;m<tam;m++){ p=(rand() % 95)+32; //p is between 32 and 126 fputc(p, out_text); } fclose(out_text); }
|
|
|
En línea
|
No hay problema sin solución, solo personas que no quieren resolverlo.
|
|
|
LaiaxanIV
Desconectado
Mensajes: 57
|
Lo que has implementado es un algoritmo ya existente llamado Vigènere. Este algoritmo de cifrado es bastante fácil de descifrar. Lo único que se tiene que hacer es buscar patrones repetidos en el texto cifrado, así puedes conocer la longitud de la clave. A partir de ahí, se crea una matriz de N x M, donde N es la longitud de la clave y M longitud del texto cifrado/N. Así, finalmente, se empieza a jugar con las frecuencias de las letras que aparecen en las columnas de esta matriz y a compararlas con el idioma del texto cifrado -si no lo conoces vas probando - (ej.: en inglés la letra más repetida es la e, después la t, la a...) y ya lo tienes. Hace poco hice una práctica que iba de eso. Lamentablemente perdí el código por un error al borrar la carpeta del github donde lo teníamos.
|
|
|
En línea
|
|
|
|
kub0x
Enlightenment Seeker
Moderador
Desconectado
Mensajes: 1.486
S3C M4NI4C
|
Vigènere depende del tamaño de clave, básicamente si el tamaño de clave es inferior al tamaño del texto a cifrar (plaintext) se reutilizará la misma clave, pudiendo observar patrones en el ciphertext, deduciendo así la clave.
Si por algún motivo el atacante tiene en su poder ciertas partes del plaintext, le sería mucho más fácil obtener ciertas partes de la clave, por lo que podría deducir aún más carácteres del plaintext. Remarcar que si el tamaño de clave es igual al tamaño del plaintext se equipararía con un One-Time-Pad (se podría decir que a cada carácter una clave).
Saludos!
|
|
|
En línea
|
|
|
|
JoseluCross
Desconectado
Mensajes: 33
Conoceréis la Verdad, y la Verdad os hará libres
|
No sabía que el cifrado tenía nombre, gracias por aclararlo.
Conociendo el problema de la estadistica implementamos un sistema para añadir caracteres aleatorios al final del texto cifrado, obviamente no sirve de nada si el atacante conoce la cantidad de caracteres son aleatorios porque siempre se colocan al final, pero si esto es desconocido ¿Es más seguro? Y otra pregunta, ¿cómo se buscan los patrones que mencionáis para ver repeticiones en el texto cifrado? y reconociendo los patrones ¿como tengo que aplicar el criptoanalisis existiendo 94 caracteres posibles? Muchas gracias nuevamente por todas sus opiniones.
|
|
|
En línea
|
No hay problema sin solución, solo personas que no quieren resolverlo.
|
|
|
LaiaxanIV
Desconectado
Mensajes: 57
|
Aunque se desconociese el número de caracteres aleatorios se podría usar la misma estrategia para descifrar el mensaje, lo único que será más costoso ya que me puedes variar el orden de repeticiones. La única manera de hacerlo completamente seguro es que la longitud de la clave sea la misma longitud que la del texto (esto es un estándar del NIST lo que ahora no me acuerdo bien del nombre). Te pongo un ejemplo: Clave: "HOLA" Mensaje: este es un mensaje super secreto y nadie nunca lo va a descifrar Cifrado: lgee lg fn tsyshxp sbdpr zsnrlhz y uooil bfnjo wo co l dlgnimflr
A simple vista, se observa como la letra l se repite cada 4 posiciones. Seguro que alomejor otras letras tambien (ten en cuenta que en textos muy largos las repeticiones llegan a ser de mas letras cosa que te asegura más precisión).
lgee lgfn tsys hxps bdpr zsnr lhzy uooi lbfn jowo cold lgni mflr
Supongamos que se que es español, por lo tanto las frecuencias son E,A,O,S,N,R.
Una vez tienes esto, solo tienes que contar por columnas la letra que mas aparece. En el primer caso es la l que aparece 5 veces. Pues para conseguir una E con una L utilizamos la H. Para conseguir la A utilizamos una L. La segunda columna estamos entre S y G que aparecen tres veces. Vamos a elegir la S porque es la buena (jijijiji) tendrías que probar xD. Por tanto para obtener la E con S... Una O! Seguiríamos así hasta haber hecho las 4 columnas.
Ten en cuenta que no siempre la E es la letra indicada, tendremos que usar la A, la O, la S... Dependerá un poco del texto. Fíjate que la última columna la letra más repetida es la R que es la 6a letra en el orden de frecuencias, para llegar a obtener la A tendríamos que haber pasado por las otras. Así tendremos que probar con unas cuantas claves, descifraremos el texto con todas las claves y elegiremos el bueno!
|
|
« Última modificación: 30 Marzo 2016, 16:35 pm por LaiaxanIV »
|
En línea
|
|
|
|
JoseluCross
Desconectado
Mensajes: 33
Conoceréis la Verdad, y la Verdad os hará libres
|
Si, lo veo, pero mi cifrado no es vigenere puro, funciona con ascii(32-126) no con el alfabeto por lo que una mayúscula y una minuscula bajo la misma letra son distintas, los espacios tambien se codifican, las comas, los puntos etc. En ese caso cual es la forma de vulnerar el cifrado. Por ejemplo OdbHhVaa__lPO_aDTVlV_aSU]VQUOe]aco\DNZSaXf\FKoZRhgOaKoRH]TWI\R` Sería "este es un mensaje super secreto y nadie nunca lo va a descifrar" con la contraseña HOLA Muchas gracias, estoy aprendiendo muchisimo
|
|
|
En línea
|
No hay problema sin solución, solo personas que no quieren resolverlo.
|
|
|
|
|