Cifrar texto por sustitución

David Vega

Programa (cómo no) criptográfico (método simétrico) que utiliza una cifra de sustitución (cambio de ASCII) para cifrar y descifrar texto plano. He modificado los métodos convencionales para hacer el texto menos vulnerable a análisis de frecuencias, pero esto depende en gran medida de la longitud de la contraseña elegida. También se sustituyen los espacios, por lo que se hace difícil “adivinar palabras”. Cada carácter de la contraseña se utiliza como seed del generador de números aleatorios, en orden y ciclos.
El programa permite escribir el texto en la consola, pegarlo en la consola y luego encriptarlo o encriptar directamente un archivo de texto que cumpla unas ciertas condiciones (sin saltos de línea o tabulaciones, ni tildes o caracteres de la tabla ASCII extendida, para evitar complicaciones). También permite, por supuesto, descifrar un archivo de texto que haya sido creado con el mismo programa.

/*Se me ocurrió hacer un "editor de texto plano"
dentro del programa, en lugar de tomar un archivo
ya hecho (aunque esto también es posible desde el
menú, yendo directamente a la opción 2, si nuestro
archivo tiene el nombre "mensaje.txt" y no contiene
tabulaciones, saltos de línea, tildes o caracteres
extraños), para realizar un input en tiempo real que
reutiliza la misma variable y no precisa de tecla
"enter" para confirmar el texto (si interrumpimos
el programa con el texto a medio escribir, se habrá
guardado en el archivo hasta donde teníamos escrito).

La opción de encriptar genera un archivo "cifrado.txt"
a partir de "mensaje.txt". Para ello, nos pide una
clave, que servirá después para descifrar el texto.
He usado un cifrado simétrico que se me ocurrió, en el
que cada letra es sustituida por otro caracter ASCII
"aleatorio", y esa "pseudoaleatoriedad" está dada por
la contraseña elegida (que actúa como seed del
generador). Sospecho que es posible atacar la cifra
debido a algún tipo de patrón en los números aleatorios
pero no he investigado mucho el tema, sólo quería hacer
un cifrado no susceptible a análisis de frecuencias.

La opción de descifrar genera un archivo "descifrado.txt"
a partir de "cifrado.txt". Para ello, nos pide la clave
con la que se cifró el texto original. Si introducimos
otra clave distinta, obtendremos caracteres aleatorios.*/

// Programa creado por David Vega

#include <stdio.h>
#include <iostream>
#include <Windows.h>
#include <conio.h>
#include <stdlib.h>
#define shh goto // Tú no has visto nada.....
using namespace std;

int main()
{
	int m;

MENU:
	cout << "\t";
	for(int i=1;i<=33;i++) cout << (char)219;
	cout << endl << "\t" << (char)219 << "\t\tMENU  \t\t" << (char)219 << endl;
	cout << "\t" << (char)219 << "\t\t       \t\t" << (char)219 << endl;
	cout << "\t" << (char)219 << "  1. Crear un archivo de texto." << (char)219 << endl;
	cout << "\t" << (char)219 << "  2. Encriptar.                " << (char)219 << endl;
	cout << "\t" << (char)219 << "  3. Descifrar.                " << (char)219 << endl;
	cout << "\t" << (char)219 << "  0. Salir.                    " << (char)219 << endl;
	cout << "\t" << (char)219 << "\t\t       \t\t" << (char)219 << endl;
	cout << "\t" << (char)219 << "\t\t       \t\t" << (char)219 << endl;
	cout << "\t";
	for(int i=1;i<=33;i++) cout << (char)219;
	cout << "\n\nElige una opcion, introduce el numero correspondiente y presiona ENTER:  ";
	cin >> m;

	// ESTA PARTE DEL PROGRAMA CREA UN ARCHIVO mensaje.txt Y ESCRIBE EN ÉL, EN TIEMPO REAL Y PERMITIENDO PEGAR TEXTO, LO QUE EL USUARIO DESEE
	if(m==1) {
	system("CLS");
	FILE *pf;
	char c = ' ';
	pf=fopen("mensaje.txt","w"); // Abrimos en modo escritura
	cout << "Escribe tu mensaje (recuerda que para pegar texto puedes hacer: \nAlt+Espacio -> Edit -> Paste)." << endl;
	cout << "No utilices tildes, tabulaciones, saltos de linea o caracteres raros. \nCuando hayas terminado, presiona Esc (ESCAPE) para salir del editor." << endl;

	for(;;)
	{
		if (GetAsyncKeyState(VK_ESCAPE)) { // Si se presiona ESCAPE ejecuta:
			SetEndOfFile(pf); // Ponemos fin al archivo (desechando lo que hay a la derecha del cursor, que son los caracteres que habíamos "borrado" con backspace).
			break; // Salimos del bucle.
		}
		else {
			c = _getch(); // Asignamos a la variable char c el valor correspondiente a la tecla que presionemos, en el mismo momento de presionarla.
			if (GetAsyncKeyState(VK_BACK)) {
				fseek(pf,-1,SEEK_CUR); // Nos vamos a la posición del char anterior en el archivo, dejando a la derecha del cursor el caracter que no queremos.
				cout << '\b'; // En pantalla movemos también el cursor atrás para sobreescribir el char no deseado.
			}
			else {
			fprintf(pf,"%c",c); // Escribimos en el archivo el caracter.
			cout << c; // Escribimos por pantalla el caracter, por cuestiones de comodidad.
			}
		}
	}

	fclose(pf);
	cout << "\n\n\tFin del proceso de escritura. Presiona \"Enter\" para volver al menu." << endl;
	cin.sync();
	cin.get();
	system("CLS");
	shh MENU;
	}

	else if(m==2) {
	system("CLS");
	FILE *pf,*pg;
	char clave[51];

	int i=0,j=0,d=0,c=0;
	cout << "Coloca tu archivo mensaje.txt en la misma carpeta que este ejecutable y presiona ENTER." << endl;
	cin.sync();
	cin.get();
	clave[0]=' ';
	cout << "\nIntroduce tu clave. Elige cualquier conjunto de caracteres ASCII imprimibles    (max. 50). Presiona ESCAPE cuando la tengas escrita." << endl;
	for(;;i++) {
		if (GetAsyncKeyState(VK_ESCAPE)) break;
		clave[i] = _getch();
		cout << "*";
	}
	j=i;
	i=0;
	cout << "\nEncriptando..." << endl;
	pf=fopen("mensaje.txt","r");
	pg=fopen("cifrado.txt","w");
	rewind(pf);
	d=getc(pf);
	while(feof(pf)==0) {
		srand((int)clave[i%(j+1)]);
		c=d+32+rand()%(95);
		fprintf(pg,"%c",(char)c);
		i++;
		d=getc(pf);

	}
	fclose(pf);
	fclose(pg);
	cout << "\n\n\tFin del proceso de cifrado. Presiona \"Enter\" para volver al menu." << endl;
	cin.sync();
	cin.get();
	system("CLS");
	shh MENU;
	}

	else if(m==3) {
		system("CLS");
		FILE *pg,*ph;
		char clave[51];

		int i=0,j=0,d=0,c=0;
		cout << "Coloca tu archivo cifrado.txt en la misma carpeta que este ejecutable y presiona ENTER." << endl;
		cin.sync();
		cin.get();
		clave[0]=' ';
		cout << "\nIntroduce tu clave. Presiona ESCAPE cuando la tengas escrita." << endl;
		for(;;i++) {
			if (GetAsyncKeyState(VK_ESCAPE)) break;
			clave[i] = _getch();
			cout << "*";
		}
		j=i;
		i=0;
		cout << "\nDescifrando..." << endl;
		pg=fopen("cifrado.txt","r");
		ph=fopen("descifrado.txt","w");
		rewind(pg);
		d=getc(pg);
		while(feof(pg)==0) {
			srand((int)clave[i%(j+1)]);
			c=d-(32+rand()%(95));
			fprintf(ph,"%c",(char)c);
			i++;
			d=getc(pg);
		}
		fclose(pg);
		fclose(ph);
		cout << "\n\n\tFin del proceso de descifrado. Presiona \"Enter\" para volver al menu." << endl;
		cin.sync();
		cin.get();
		system("CLS");
		shh MENU;
	}
	else if(m==0) return 0;
	else {
		system("CLS");
		shh MENU;
	}
}

Esta entrada fue publicada en Informática e Internet. Guarda el enlace permanente.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s