-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 /* Cifrado de Garbo. Implementado por Ezequiel Guerrero (ezequiel.guerrero@facinf.uho.edu.cu) Colaboracion de Aryan Gonzalez (aryan.gonzalez@facinf.uho.edu.cu) PGP Key ID 0xB7E20E1B en https://keyserver-beta.pgp.com Compilado en Borland C++ 3.1 y Visual C++.NET */ #include #include #include #include #include #include // PROTOTIPOS int Pos( const char*,char ); int Resto( int a,int b ); void FilaColumna( const char ch, int * f,int * c ); char * SubsEncrypt( const char * plain ); char * SubsDecrypt( const char * cipher ); char * TransEncrypt( const char * plain,int inic ); char * TransDecrypt( const char * cipher,int inic ); char * GarboEncrypt( const char * plain,int dia,int mes ); char * GarboDecrypt( const char * cipher,int dia,int mes ); void Print5Screen( const char * s ); char * Prepare( const char * s ); // CONSTANTES const char * Orden = "PAGWSLNBT_CHUIQMXFOJ[VYK\\D]Z^ER"; const char Matriz[5][5] = { {'L','A','C','O','N'}, {'F','I','Z','E','G'}, {'B','R','T','D','H'}, {'J','M','P','Q','S'}, {'U','V','W','X','Y'} }; // MAIN // Maxima cantidad de caracteres del mensaje #define MAX_CHARS 1000 int main( int argc, char *argv[] ){ int dia = 0,mes = 0; char entrada[MAX_CHARS + 1]; char op = NULL; do{ printf( "Desea (C)ifrar o (D)escifrar? " ); scanf( "%c",&op ); op = toupper( op ); }while( op != 'C' && op != 'D' ); do{ printf( "Entre dia: " ); scanf( "%i",&dia ); }while( dia < 1 && dia > 31 ); do{ printf( "Entre mes: " ); scanf( "%i",&mes ); }while( mes < 1 && mes > 12 ); printf( "Teclee texto de entrada (%d chars max):\n",MAX_CHARS ); /* Nota: Por inexperiencia en el trabajo con cadenas, no he logrado entrarlas al programa de otra forma que no sea combinando estas dos maneras. Sorry. */ scanf( "%0s",entrada ); fgets( entrada,MAX_CHARS + 1,stdin ); char * tmp = Prepare( entrada ); char * salida = NULL; if( op == 'C' ) salida = GarboEncrypt( tmp,dia,mes ); else salida = GarboDecrypt( tmp,dia,mes ); printf( "\nTexto %s:", op == 'C' ? "plano" : "cifrado" ); Print5Screen( tmp ); printf( "\nTexto %s:", op == 'D' ? "plano" : "cifrado" ); Print5Screen( salida ); delete( salida ); delete( tmp ); system( "pause" ); return 0; } // METODOS /* Se utiliza en la sustitucion para tratar a la primera fila/columna como la que sigue a la ultima fila/columna */ int Resto( int a,int b ){ return((( a % b ) + b ) % b ); } // Coordenadas de una letra en la matriz de sustitucion void FilaColumna( const char ch,int * f,int * c ){ int test = 0; for( int i = 0; i < 5; i++ ){ for( int j = 0; j < 5; j++ ) if( Matriz[i][j] == ch ){ *f = i; *c = j; test = 1; break; } if( test ) break; } } // Primera fase: sustitucion polialfabetica // Cifrado char * SubsEncrypt( const char * plain ){ int len = (int)strlen( plain ); char * cipher = new char[len + 1]; if( !len ){ cipher[0] = NULL; }else{ int f,c; for( int i = 0; i < len; i++ ){ if( plain[i] != 'K' ){ FilaColumna( plain[i],&f,&c ); switch( i % 5 ){ case 0: cipher[i] = Matriz[Resto( f - 1,5 )][c]; break; case 1: cipher[i] = Matriz[f][Resto( c + 1,5 )]; break; case 2: cipher[i] = Matriz[Resto( f + 1,5 )][c]; break; case 3: cipher[i] = Matriz[f][Resto( c - 1,5 )]; break; default: cipher[i] = plain[i]; } }else cipher[i] = plain[i]; cipher[i + 1] = NULL; } } return cipher; } // Descifrado char * SubsDecrypt( const char * cipher ){ int len = (int)strlen( cipher ); char * plain = new char[len + 1]; if( !len ){ plain[0] = NULL; }else{ int f,c; for( int i = 0; i < len; i++ ){ if( cipher[i] != 'K' ){ FilaColumna( cipher[i],&f,&c ); switch( i % 5 ){ case 0: plain[i] = Matriz[Resto( f + 1,5 )][c]; break; case 1: plain[i] = Matriz[f][Resto( c - 1,5 )]; break; case 2: plain[i] = Matriz[Resto( f - 1,5 )][c]; break; case 3: plain[i] = Matriz[f][Resto( c + 1,5 )]; break; default: plain[i] = cipher[i]; } }else plain[i] = cipher[i]; plain[i + 1] = NULL; } } return plain; } // Segunda fase: Transposicion columnar // Cifrado char * TransEncrypt( const char * plain,int inic ){ /* La cadena constante Orden almacena el orden en que se leen las columnas. Si sustituimos cada caracter por su valor ASCII y les restamos 64, obtenemos el encabezado de la tabla de transposicion. */ int k = Pos( Orden,char( inic + 64 )); int len = (int)strlen( plain ); int i; int CantFilas = (int)ceil( double( len + k ) / double(31) ); /* El arreglo Tabla funciona como un arreglo bidimensional (de CantFilas filas y 31 columnas) o unidimensional a conveniencia. Toma el rol de la tabla en que se aplica la transposicion. */ char * Tabla = new char[(CantFilas * 31) + 1]; // Usamos los caracteres # como rellenos de la "tabla". for( i = 0; i < CantFilas * 31; i++ ) Tabla[i] = '#'; Tabla[CantFilas * 31] = NULL; /* Colocamos las letras del texto de entrada en las posiciones que le corresponden (usando a Tabla como unidimensional, pero viendola como bidimensional). */ for( i = 0; i < len; i++ ) Tabla[i + k] = plain[i]; char * cipher = new char[len + 1]; int c = 0; /* Leemos por columnas, pero tomando solo las letras, y dejando atras el "relleno". */ for( i = 0; i < 31; i++ ){ k = Pos( Orden,char( i + 65 )); for( int j = 0; j < CantFilas; j++ ) if( Tabla[j * 31 + k] != '#' ){ cipher[c] = Tabla[j * 31 + k]; c++; } } cipher[c] = NULL; delete( Tabla ); return cipher; } // Descifrando char * TransDecrypt( const char * cipher,int inic ){ int k = Pos( Orden,char( inic + 64 )); int len = (int)strlen( cipher ); int CantFilas = (int)ceil( double( len + k ) / double(31) ); int i, j; char * Tabla = new char[(CantFilas * 31) + 1]; for( i = 0; i < CantFilas * 31; i++ ) Tabla[i] = '#'; Tabla[CantFilas * 31] = NULL; /* Utilizando a Tabla de una manera similar, usamos el punto (.) para indicar un patron de celdas permitidas en las cuales se puede escribir (en columnas). */ for( i = 0; i < len; i++ ) Tabla[i + k] = '.'; int c = 0; for( i = 0; i < 31; i++ ){ k = Pos( Orden,char( i + 65 )); for( j = 0; j < CantFilas; j++ ) if( Tabla[j * 31 + k] == '.' ){ Tabla[j * 31 + k] = cipher[c]; c++; } } char * plain = new char[len + 1]; c = 0; for( i = 0; i < CantFilas * 31; i++ ) if( Tabla[i] != '#' ){ plain[c] = Tabla[i]; c++; } plain[c] = NULL; delete( Tabla ); return plain; } // La funcion central: cifrando char * GarboEncrypt( const char * plain,int dia,int mes ){ // Sustitucion usando la matriz char * tmp = SubsEncrypt( plain ); // Transposicion usando el dia char * tmp1 = TransEncrypt( tmp,dia ); delete( tmp ); // Transposicion usando el mes char * tmp2 = TransEncrypt( tmp1,mes ); delete( tmp1 ); return tmp2; } // la funcion central: descifrando char * GarboDecrypt( const char * cipher,int dia,int mes ){ // Transposicion usando el mes char * tmp2 = TransDecrypt( cipher,mes ); // Transposicion usando el dia char * tmp1 = TransDecrypt( tmp2,dia ); delete( tmp2 ); // Sustitucion usando la matriz char * tmp = SubsDecrypt( tmp1 ); delete( tmp1 ); return tmp; } // Imprimir los mensajes en formato de grupos de cinco letras void Print5Screen( const char * s ){ int len = (int)strlen( s ); for( int i = 0; i < len; i++ ){ if( !( i % 50 )) printf( "\n" ); else if( !( i % 5 )) printf( " " ); printf( "%c",s[i] ); } printf( "\n" ); } /* Preparar la cadena antes de empezar a utilizarla (incluye rellenar con X) */ char * Prepare( const char * s ){ int len = (int)strlen( s ); len += 5 - len % 5; char * tmp = new char[len + 1]; int c = 0; for( int i = 0; i < (int)strlen( s ); i++ ) if( s[i] >= 'A' && s[i] <= 'Z' ){ tmp[c] = s[i]; c++; }else if( s[i] >= 'a' && s[i] <= 'z' ){ tmp[c] = s[i] - ( 'a' - 'A' ); c++; } int m = ( c % 5 ? 5 - c % 5 : 0 ); while( m ){ tmp[c] = 'X'; c++; m--; } tmp[c] = NULL; return tmp; } // Devuelve la posicion de un caracter en un arreglo. int Pos( const char * str,char ch ){ int i; int len = (int)strlen( str ); int test = 0; for( i = 0; i < len; i++ ) if( str[i] == ch ){ test = 1; break; } return( test ? i : -1 ); } -----BEGIN PGP SIGNATURE----- Version: PGP 8.0 Comment: De TODOS y para el bien de TODOS. iQA/AwUBQjTnnMTzfEC34g4bEQIuvgCg8A68xGGa7xbJdlFQcNT0pzxQ7NsAn1xr 2o1/oF6h4uSdl+APQ8M1Oujv =UIAl -----END PGP SIGNATURE-----