domingo, 24 de septiembre de 2017

Cifrado RC4

RC4 es un esquema de cifrado de flujo (no basado en bloques) simétrico.

Es un esquema de cifrado extremadamente simple y puede implementarse en software de forma muy eficiente. Esto lo ha convertido en uno de los esquemas de cifrado más utilizados del mundo. RC4 fue excluido enseguida de los estándares de alta seguridad por los criptógrafos y algunos modos de usar el algoritmo de criptografía RC4 lo han llevado a ser un sistema de criptografía muy inseguro, incluyendo su uso WEP. No está recomendado su uso en los nuevos sistemas, sin embargo, algunos sistemas basados en RC4 son lo suficientemente seguros para un uso común.


Descripción


RC4 es un algoritmo simple, este consiste en 2 algoritmos:

1-Algoritmo de programacion de claves (KSA)
2-Algoritmo de generacion Pseudo-Aleatoria (PRGA).

Cada uno de estos algoritmos usa un array de 256 números en el que ambos son únicos en cuanto a rango y su valor va desde 0 hasta 255. Todos los números de 0 a 255 existen dentro del array, pero están solo mezclados de diferentes maneras, el KSA se encarga de realizar la primera mezcla en el S-Box, basado en el valor de la semilla dada dentro de él, y esta "semilla" puede ser de 256 bytes de largo.


Algoritmo


Primero, el S-box array, es decir nuestro arreglo S[] es llenado con valores secuenciales desde 0-255, entonces, el otro array de 256-bytes es llenado con el valor de la "semilla", repitiendo como sea necesario hasta que todo el array es llenado. Este array será llamado K, entonces el array S es mezclado usando el siguiente pseudocódigo:




Una vez que eso es hecho, la S-box es intercambiada basándose en el valor de la "semilla". Esa es la "Key" programada para el algoritmo, algo sencillo.

Ahora que hemos generado la "Key" se usa el Algoritmo de generacion Pseudo-Aleatoria (PRGA). Este algoritmo tiene 2 contadores, el i y la j, en el cual ambos son inicializados en 0 para comenzar. Después de eso, cada byte de la "Key" generada es usada en el siguiente Pseudo-Code:





El valor expuesto del byte de S[t] es el primer byte del keystream, repitiéndose el algoritmo descrito para conseguir bytes adicionales de keystream.

RC4 es lo suficientemente sencillo como para ser almacenado e implementado al facilmente, aunque la robustez de dicho algoritmo depende, en gran medida, de la implementación y utilización realizada, existiendo graves problemas conocidos en la implementación del sistema de cifrado WEP, diseñado para ofrecer confidencialidad en redes Wireless.

Implementación


Bueno he tomado el ejemplo y lo he modificado para pasarlo por parámetros el texto a cifrar y la clave y he comentado algunas partes para comprenderlo mejor, el código lo pueden visualizar mejor desde aqui.

En resumen la función void rc4_generar_vector(unsigned char *key, unsigned int key_length) recibe como parámetro la clave la cual ingresamos y el tamaño de nuestra clave. Luego inicializa nuestro Array S[] asignándoles valores secuenciales desde el 0-255 y luego genera el Array S[] pero con los valores intercambiados por el algoritmo mostrado en la primera imagen que utiliza la clave ingresada al inicio.

Por otro lado la función unsigned char rc4_salida()  genera el cifrado del texto ingresado inicialmente aplicando un XOR entre el caracter x del texto (texto[x]) y un valor "pseudo-aleatorio" del Array S[] generado anteriormente.

Bueno en la siguiente imagen podemos visualizar el programa funcionando:

*Nota: Podemos observar como al varial el texto a cifrar agregandole una letra mas, el resultado varia solo al final.


El codigo:

/**
    Autor: PaoloRamirez
    Tema: Cifrado RC4
    Link: https://www.facebook.com/PaoloProgrammer/
**/

#include <stdio.h>
#include <string.h>
#include <stdlib.h> 

unsigned char S[256];
unsigned int i, j;

/**
    Intercambiar valores entre i y j
**/
void intercambiar(unsigned char *s, unsigned int i, unsigned int j) 
{
    unsigned char temp = s[i];
    s[i] = s[j];
    s[j] = temp;
}

/**
    KSA - Algoritmo de programacion de claves
**/
void rc4_generar_vector(unsigned char *key, unsigned int key_length) 
{

    //Asignar valores iniciales al Array S[]
    for (i = 0; i < 256; i++)
    {   
        S[i] = i;
    }
 
    //Genera semilla con la clave ingresada, altera los valores de S[]
    for (i = j = 0; i < 256; i++) 
    {   
        j = (j + key[i % key_length] + S[i]) & 255;
        intercambiar(S, i, j);  
    }
 
    i = j = 0;
}
 
/**
    PRGA - Algoritmo de generacion Pseudo-Aleatoria
**/
unsigned char rc4_salida() 
{
    i = (i + 1) & 255;
    j = (j + S[i]) & 255;

    intercambiar(S, i, j);

    return S[(S[i] + S[j]) & 255];
}

int main(int argc, char **argv) 
{

    int len_texto,len_clave;
    len_texto=strlen(argv[1]);
    len_clave=strlen(argv[2]);

    /**
        Texto inicial
        Clave de cifrado
    **/
    //Tamaño de cadena = len+fincadena \0
    char texto[len_texto+1];
    char clave[len_clave+1];

    //Format
    memset(texto,0,sizeof(texto));
    memset(clave,0,sizeof(clave));

    //Copiar a variables
    strcpy(texto,argv[1]);
    strcpy(clave,argv[2]);
 
    
    int x;
    rc4_generar_vector(clave, strlen(clave));

    for (x = 0; x < strlen(texto); x++)
    {
        printf("%02X", texto[x] ^ rc4_salida());
    }

    printf("\n");
    
}


Enlaces:



Referencias:


sábado, 23 de septiembre de 2017

Quitar el sonido de inicio en Ubuntu

Después de usar un tiempo Ubuntu a algunos -bueno al menos a mí- comienza a molestar el sonido de inicio de Ubuntu y mas que todo porque en mi caso ese sonido se reproduce con el volumen máximo, por lo cual estuve buscando alguna forma de desactivarlo. Encontré algunas formas de hacerlo instalando programas, pero supuse que había alguna forma de hacerlo sin necesidad de aquellos programas.


Bueno debemos hacer lo siguiente:

  • Primero debemos tener un archivo con extensión .ogg que sera el sonido que reemplazará al sonido de inicio de Ubuntu, en mi caso yo lo tengo en mi escritorio y se llama audio.gg el cual antes lo modifique reduciéndolo a 7 segundos y le he quitado el sonido.
    • Pueden descargarlo aqui.
  • Renombramos nuestro nuevo sonido de inicio el cual sera uno sin sonido:
    • $ mv ~/Escritorio/audio.ogg ~/Escritorio/system-ready.ogg
  • Ahora lo siguiente es copiar este archivo a la ubicación donde esta el system-ready.ogg el cual podemos visualizarlo en la siguiente imagen:
*Nota: en mi caso el nuevo audio se encuentra en mi Escritorio, si su audio esta en otra ubicación deberán indicar su ubicación en vez de la que uso yo.
  • Si queremos verlo por nuestra cuenta debemos hacer lo siguiente:
    • $ cd /usr/share/sounds/ubuntu/stereo
    • $ ls
  • Reemplazamos el sonido de inicio actual por el sonido nuevo, para ello necesitamos privilegios:
    • $ sudo cp ~/Escritorio/system-ready.ogg /usr/share/sounds/ubuntu/stereo
  • Y listo, eso es todo. Si quieren volver a tener el sonido de inicio de Ubuntu ( tambores) pueden descargarlo de aqui.







lunes, 18 de septiembre de 2017

S-Box

En criptografía, una S-Box (substitution box) es un componente básico de los algoritmos de cifrado de clave simétrica, son tablas de busqueda que mapean n bits a m bits, en general, una S-Box toma un número m de bits de entrada y los transforma en n bits de salida. En los cifradores por bloques son usadas a menudo para oscurecer la relación existente entre texto plano y texto cifrado (la propiedad de confusión). En muchos casos las S-Boxes son elegidas cuidadosamente para ser resistentes al criptoanálisis.

Hay varias maneras de construir buenas S-boxes para cifrados, así como varias maneras de medirlas. Algunos diseñadores usan una aproximación matemática rigurosa al usar funciones curvilíneas (o relacionadas) para crear S-boxes que puedan ser probadas como resistentes contra algunos ataques particulares. Otros diseñadores usan aproximaciones heurísticas, lo cual conduciría a que las s-boxes sean más difíciles de manejar en pruebas matemáticas, pero pueden tener beneficios adicionales (como varias opciones diferentes de implementación).

La S-Box puede ser la única parte no lineal del cifrado, este es el caso del cifrado en bloque DES, y de esta manera debe ser considerado como la parte más importante del algoritmo. De hecho, muchos consideran a las S-boxes DES tan buenas que las usan en sus propios diseños.

Las Tablas prefijadas se usan en algunos algoritmo mientras que otros cifradores usan S-Boxes dependientes de la clave, como en Blowfish y Twofish.

S-Box 6x4 bits

La imagen nos muestra una S-Box de 6x4 bits:

En donde nuestra entrada es de 6 bits y nos devolverá una salida de 4bits, de los cuales para la entrada esta dividido asi:

  • 4 bits de entrada internos
  • 2 bits de entrada externos
Por ejemplo si tenemos una entrada de "011011", los bits externos serian "011011" (01) mientras que los bits internos serian "011011" (1101).


Implementación


Bueno para la implementación he escrito en una tabla los valores que tendrá nuestra S-Box de 6x4, tomaremos como parámetro una cadena de entrada, la cual evaluamos bit a bit, cada 6 bits tomaremos como entrada y almacenaremos la salida en la variable temporal, pues al solo tener 4 bits inicialmente, tienes que tener los siguientes 4 bits para completar los 8 bits (1 byte).

Pueden ver el codigo aqui.

Compilamos y ejecutamos:

$ gcc S-Box.c -o sbox

$ ./sbox texto1234

Podemos comprobar que los valores que imprime, si los ubicamos en la tabla, son los mismos al resultado mostrado, van en el siguiente orden:

Bits internos (4 bit) - bits externos (2 bits) - valor en la tabla (4 bits de salida) - valor en la tabla desplazado 4 bits a la izquierda


*Nota: la salida normalmente son caracteres que la consola no puede mostrarnos, pero haciendo un recorrido por la cadena de salida, podemos ver que esta todo normal.
*Nota 2: Como mencioné anteriormente necesitamos 8 bits, por lo cual los primeros 4 bits desplazamos 4 bits a la izquierda y le sumamos los siguientes 4 bits (en el ejemplo el primer valor es 8 y le suma el seguido que es 1, por ello el resultado es 81 en hexadecimal).


El código prácticamente he tratado de comentar cada parte para que sea mas comprensible:


/**
 Autor: PaoloRamirez
 Tema: S-Box o Cajas-S (ejemplo S-Box de 6x4bits)
 Link: https://www.facebook.com/PaoloProgrammer/
**/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char **argv)
{
 if(argc!=2)
 {
  perror("Insertar 1 parametro (p1:texto)");
  exit(0);
 }

 int len_texto,len_resultado;
 len_texto=strlen(argv[1]);
 len_resultado=len_texto*2/3;


 /**
  Texto inicial que ingresa al S-Box
 **/
 //Tamaño de cadena = len+fincadena \0
 char texto[len_texto+1];
 char resultado[len_resultado+1];

 //Format
 memset(texto,0,sizeof(texto));
 memset(resultado,0,sizeof(resultado));

 //Copiar a variable
 strcpy(texto,argv[1]);


 printf("Entrada: %s\n", texto);


 /**
  Tabla prefijada 6x4 bits
 **/
 char tabla[4][16]; //Externo x Interno


 tabla[0][0]=2;tabla[0][1]=12;tabla[0][2]=4;tabla[0][3]=1;
 tabla[0][4]=7;tabla[0][5]=10;tabla[0][6]=11;tabla[0][7]=6;
 tabla[0][8]=8;tabla[0][9]=5;tabla[0][10]=3;tabla[0][11]=15;
 tabla[0][12]=13;tabla[0][13]=0;tabla[0][14]=14;tabla[0][15]=9;
 tabla[1][0]=14;tabla[1][1]=11;tabla[1][2]=2;tabla[1][3]=12;
 tabla[1][4]=4;tabla[1][5]=7;tabla[1][6]=13;tabla[1][7]=1;
 tabla[1][8]=5;tabla[1][9]=0;tabla[1][10]=15;tabla[1][11]=12;
 tabla[1][12]=3;tabla[1][13]=9;tabla[1][14]=8;tabla[1][15]=6;
 tabla[2][0]=4;tabla[2][1]=2;tabla[2][2]=1;tabla[2][3]=11;
 tabla[2][4]=12;tabla[2][5]=13;tabla[2][6]=7;tabla[2][7]=8;
 tabla[2][8]=15;tabla[2][9]=9;tabla[2][10]=12;tabla[2][11]=5;
 tabla[2][12]=6;tabla[2][13]=3;tabla[2][14]=0;tabla[2][15]=14;
 tabla[3][0]=11;tabla[3][1]=8;tabla[3][2]=12;tabla[3][3]=7;
 tabla[3][4]=1;tabla[3][5]=14;tabla[3][6]=2;tabla[3][7]=13;
 tabla[3][8]=6;tabla[3][9]=15;tabla[3][10]=0;tabla[3][11]=9;
 tabla[3][12]=12;tabla[3][13]=4;tabla[3][14]=5;tabla[3][15]=3;

 /**
  Entrada[6] - Salida[4]
 **/

 // variables "interno" y "externo" para acceder a la tabla prefijada
 int i,j,interno=0,externo=0;
 //variable temporal para saber el binario al aplicar un &
 int xbit=0x80; 
 //suma interna varia entre 0 y 15 (0x8 para iniciar sabiendo el bit en la posicion 4)
 int suma_int=0x8; 
 //suma externa varia entre 0 y 3  (0x2 para iniciar sabiendo el bit en la posicion 2)
 int suma_ext=0x2;

 int cont=0;

 int ind_resultado=0; //indice de la variable resultado (que sera el resultado final)
 int temp_resultado;
 int agregar=0;

 for (i = 0; i < len_texto; i++)
 {

  for (j = 0; j < 8; j++)
  {   
   
   /**
    Obtener valores de "interno" y "externo"
   **/

   //Aplicar & para saber si existe el bit en esa posicion
   //donde xbit tiene como valor la posicion a evaluar

   if(texto[i] & xbit)
   {
    //Sumarle el valor de "suma_x" en caso exista el bit en esa posicion
    if(cont==0 || cont==5)
    {
     externo+=suma_ext;
    }
    else
    {
     interno+=suma_int;
    }
   }


   //Hacer desplazamiento a la derecha >>
   xbit=xbit>>1;

   //Bits 0 y 5 para externo
   if(cont==0) { suma_ext=suma_ext>>1;}

   //Bits 1,2,3,4 para interno
   else { suma_int=suma_int>>1; }

   //Control de 6 bits de entrada
   if (cont==5)
   {
    //Obtener primeros 4 bits
    if (agregar==0)
    {
     temp_resultado=tabla[externo][interno]<<4;
     agregar++;
    }
    //Obtener los siguientes 4 bits y agregar al resultado de salida
    else
    {
     temp_resultado+=tabla[externo][interno];
     resultado[ind_resultado]=temp_resultado;
     agregar=0;
     ind_resultado++;
    }

    //Test para mostrar valores de acceso a la tabla
    printf("Interno:%x - Externo:%x - Valor-Tabla:%x - %x\n,
    interno,externo,tabla[externo][interno],temp_resultado);

    //Inicializar variables cada 6 bits evaluados
    cont=0;
    suma_int=0x8;
    suma_ext=0x2;
    interno=0;
    externo=0;
   }
   else
   {
    cont++;
   }
  }
  //reiniciar temporal a bit 8: 0b1000 0000 -> 0x80 -> 128
  xbit=0x80;
 }
 printf("\nSalida: %s\n",resultado);
 
}


*Nota: Tener en cuenta que según el tamaño de nuestra cadena, sera el tamaño de la salida, al ser un S-Box de 6x4, frecuentemente utilizan un S-Box de NxN.


Enlaces



Referencias

domingo, 10 de septiembre de 2017

Cifrado XOR

El cifrado XOR es un algoritmo de cifrado basado en el operador binario XOR, el cual es una operacion OR exclusiva (XOR).

El operador XOR

Para entender que hacer el operador XOR podemos observar la siguiente imagen:



Ademas se cumple que:

Si aplicamos a una cadena A XOR 0 = A , nos dará como resultado la misma cadena.
Si aplicamos a una cadena B XOR A = C y a este resultado le volvemos a aplicar C XOR A = B , nos dará como resultado la cadena inicial, es decir B.

Ejemplo


Cifrado cadena-clave (8bits = 1byte = 1 caracter)

Por ejemplo si de entrada tenemos la palabra "FISI" (01000110 01001001 01010011 01001001) y la ciframos con la clave (01010101) que su valor en Ascii es 85 y esta representado como "U", entonces tenemos asi:

01000110 01001001 01010011 01001001

01010101 01010101 01010101 01010101
-----------------------------------------------------------
00010011 00011100 00000110 00011100


Cifrado cadena-clave ( n caracteres)

Si tenemos una cadena de entrada "FISI" (01000110 01001001 01010011 01001001) y clave "1234" (00110001 00110010 00110011 00110100)

01000110 01001001 01010011 01001001

00110001 00110010 00110011 00110100
-----------------------------------------------------------
01110111 01111011 01100000 01111101

En esto consiste basicamente el cifrado XOR, el cual tenemos como entrada el texto a cifrar "FISI" (B) y la clave de cifrado "1234" (A) , para descifrar el texto solamente tendriamos que volver a aplicar un XOR al texto cifrado "w{`}" (C) , que nos dara como resultado la cadena inicial "FISI" (B).

Descifrado cadena-clave ( n caracteres)

Tenemos como entrada el texto cifrado "w{`}" (01110111 01111011 01100000 01111101) y la clave utilizada anteriormente "1234" (00110001 00110010 00110011 00110100) y le aplicamos XOR:


01110111 01111011 01100000 01111101

00110001 00110010 00110011 00110100
-----------------------------------------------------------
01000110 01001001 01010011 01001001

Como resultado hemos obtenido la cadena "FISI" (01000110 01001001 01010011 01001001) que es la cadena que inicialmente ingresamos.


Implementación


En el cifrado de feistel utilizamos una función en la cual se aplicaba un XOR entre 2 caracteres. En este ultimo ejemplo es casi lo mismo, realizaremos un pequeño programa el cual aplicara el cifrado XOR a un texto y clave ingresadas por parámetros.

Pueden ver el código desde aqui.

El código:


/**
 Autor: PaoloRamirez
 Tema: Aplicar XOR a una cadena con una clave de N bytes
 Link: https://www.facebook.com/PaoloProgrammer/
**/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
 
int main(int argc, char *argv[])
{
 if(argc!=3)
 {
  perror("Insertar 2 parametros (p1:texto, p2:clave)");
  exit(0);
 }

 int len_texto,len_clave;
 len_texto=strlen(argv[1]);
 len_clave=strlen(argv[2]);

 /**
  Texto inicial
  Clave de cifrado
 **/
 //Tamaño de cadena = len+fincadena \0
 char texto[len_texto+1]; //L+R
 char clave[len_clave+1]; //Ki

 //Format
 memset(texto,0,sizeof(texto));
 memset(clave,0,sizeof(clave));

 //Copiar a variables
 strcpy(texto,argv[1]);
 strcpy(clave,argv[2]);

 printf("Texto: %s\n", texto);
 printf("Clave: %s\n\n", clave);

 //Aplicando XOR;  texto[i] XOR clave[0]
 int i;
 for (i = 0; i < len_texto; i++)
 {
  /* code */
  texto[i] = texto[i]^clave[i]; //Iteramos tanto en el texto[i] como en la clave[i]
 }

 printf("Texto cifrado: %s\n", texto);
}


Clave 8 bits (1 byte):

Para el primer ejemplo solo tomo el primer caracter del segundo parametro, es decir, clave[0].
En la imagen podemos ver como parametros "FISI" y "0" que al aplicar XOR nos da como resultado la cadena "vycy".

Nota: No ingrese que como clave "U" como en el ejemplo porque nos da como resultado caracteres que no se pueden mostrar. Debo agregar que la clave ingresada "0" es el carácter '0' y no el valor 0.

Como paso final aplicamos XOR a la cadena resultante y obtenemos el texto ingresado inicialmente "FISI".

Clave N bytes:

En la imagen podemos ver como parámetros "FISI" y "1234" que al aplicar XOR nos da como resultado la cadena "w{`}".

Nota: Como se logra visualizar antes de la comilla ' agrego el simbolo \ pues es un caracter especial y no podemos pasarlo como parametro directamente.

Como vemos al aplicar un XOR a la cadena cifrada y la misma clave utilizada para cifrar, obtenemos como resultado la cadena inicialmente ingresada, para nuestro ejemplo "FISI". 

El operador XOR es muy común como parte de cifrados mas complejos. Sin embargo, por si solo el cifrado XOR es muy vulnerable y es fácil de obtener la clave a través del analisis de varios mensajes cifrados con la misma clave.


Enlaces


https://github.com/phaoliop/Programming_C-Cplus/blob/master/C/Cifrado/xor_8bits.c

https://github.com/phaoliop/Programming_C-Cplus/blob/master/C/Cifrado/xor_nbytes.c

https://github.com/phaoliop/Programming_C-Cplus/blob/master/C/Cifrado/xor.c

Referencias

Cifrado de Feistel

Empezando a buscar en que entretenerme un rato, comence a buscar algun tipo de cifrado, despues de un rato logre concluir que debía empezar desde los metodos utilizados antes o los metodos en los cuales estan "basados" los actuales métodos de cifrados, asi que encontre el Algoritmo de Feistel el cual hoy les presentaré.

Es un método de cifrado en bloque diseñado por Horst Feistel, también se le conoce como Red Feistel o Cadena de Feistel, una gran cantidad de cifrado por bloques lo utilizan, siendo el mas conocido el algoritmo Data Encryption Standard (DES) que mas adelante probablemente estaré publicando algo al respecto, recordemos que los tipos de cifrado según sus algoritmos puede ser: cifrado en bloque, donde el cifrado se realiza bloque a bloque y el cifrado en flujo, donde el cifrado se realiza bit a bit.

El algoritmo


Este algoritmo se denomina simétrico por rondas, es decir, realiza siempre las mismas operaciones un número determinado de veces (denominadas rondas). Los pasos de la red de Feistel son entre algunos más:
  1. Se selecciona una cadena, N, normalmente de 64 o 128 bits (para mi ejemplo 64 bits), y se la divide en dos subcadenas, L y R, de igual longitud (N/2)
  2. Se toma una función, F, y una clave Ki
  3. Se realizan una serie de operaciones complejas con F y Ki y con L o R (solo uno de ellas)
  4. La cadena obtenida se cambia por la cadena con la que no se han realizado operaciones, y se siguen haciendo las rondas.

Construcción del algoritmo


Las operaciones básicas de una red de Feistel son las siguientes: se descompone el texto plano en dos piezas iguales, (Lo, Ro). Para realizar el cifrado en cada ronda i= 0,1,2...n-1 , se calcula:

 
donde f es una función y Ki son cada una de las subclaves aplicadas a cada iteración (para mi ejemplo utilizo cada carácter de una clave de 8 bytes, es decir: K[i] ). Luego a Li-1 se le aplica un XOR (vease aqui) con el resultado de aplicar la función f (Ri-1, Ki). El texto cifrado viene dado por la concatenación de Ln y Rn.

Para el descifrado las operaciones que hay que realizar son:



Otra forma de ver el algoritmo es con esta imagen, la cual utilicé para guiarme al hacer código.



Código (Hecho en C)

Para este ejemplo utilicé una cadena de 8 caracteres como primer parametro (argv[1]) y una cadena de 8 caracteres como segundo parametro (argv[2]). La funcion F es el dato pasado como parametro (dato[i]) mas el Ascii del residuo de la division de pwd entre 17 (pwd%17).
Para compilacion ejecutar en terminal:

$gcc nombre_archivo.c -o ejecutable

$./ejecutable micadena miclave1

Donde "micadena" es la cadena a encriptar y "miclave1" es la clave que se utilizará para el cifrado.

Pueden ver el código desde aqui.

El código:

/**
 Autor: PaoloRamirez
 Tema: Cifrado de Feistel
 Link: https://www.facebook.com/PaoloProgrammer/
**/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>


void fun_aplicada(char dato[],char pwd);
void fun_xor(char dato1[], char dato2[]);

int main(int argc, char **argv)
{
 if(argc!=3)
 {
  perror("Insertar 2 parametros (p1:texto, p2:clave)");
  exit(0);
 }

 int len_texto,len_clave;
 len_texto=strlen(argv[1]);
 len_clave=strlen(argv[2]);

 /**
  Texto inicial
  Clave de cifrado
 **/
 //Tamaño de cadena = len+fincadena \0
 char texto[len_texto+1]; //L+R
 char clave[len_clave+1]; //Ki

 //Format
 memset(texto,0,sizeof(texto));
 memset(clave,0,sizeof(clave));

 //Copiar a variables
 strcpy(texto,argv[1]);
 strcpy(clave,argv[2]);


 printf("Texto: %s\n", texto);
 printf("Clave: %s\n\n\n", clave);

 /**
  CIFRADO
 **/
 char izquierda[(len_texto/2)+1]; //L
 char derecha[(len_texto/2)+1]; //R

 //Format
 memset(izquierda,0,sizeof(izquierda));
 memset(derecha,0,sizeof(derecha));

 strncpy(izquierda,texto,len_texto/2);
 strcpy(derecha,texto+len_texto/2);

 //Valores iniciales
 printf("Texto[0]---> L(0) = %s\tR(0) = %s\n", izquierda, derecha);

 //Ciclo iterativo de L0-N y R0-N)
 int i;
 char temp_fun[(len_texto/2)+1];
 char temp_xor[(len_texto/2) +1];
 memset(temp_fun,0,sizeof(temp_fun));
 memset(temp_xor,0,sizeof(temp_xor));


 for (i = 0; i < len_texto; i++)
 {
  //Asignar a Li+1 <- Ri
  strcpy(temp_xor,izquierda); //Obtengo en temp_xor: Li
  strcpy(izquierda,derecha); //Obtengo en izquierda: Li+1

  //Aplicar f(Ri, Ki) ; donde Ri: derecha , Ki: clave
  strcpy(temp_fun,derecha);
  fun_aplicada(temp_fun,clave[i]); //Obtengo en temp_fun: f(Ri, Ki)

  //Aplicar XOR: Li XOR f(Ri,Ki)
  fun_xor(temp_xor,temp_fun); //Obtengo en temp_xor: Li XOR f(Ri,Ki)

  //Asignar a Ri+1 <- Resultado de Li XOR f(Ri,Ki)
  strcpy(derecha,temp_xor); //Obtengo en derecha: Ri+1

  //Mostrar valores i+1
  printf("Texto[%i]---> L(%i) = %s\tR(%i) = %s\n", i+1, i+1, izquierda, i+1, derecha);
 }

 printf("Cifrado: L() = %s\tR() = %s\n", izquierda, derecha);
 printf("%s\n", "--------------------------------------");

 /**
  DESCRIFRADO
 **/
 for (i = len_texto-1; i >= 0; i--)
 {
  //Asignar a Ri-1 <- Li
  strcpy(temp_xor,derecha); //Obtengo en temp_xor: Ri
  strcpy(derecha,izquierda); //Obtengo en derecha: Ri-1

  //Aplicar f(Li, Ki) ; donde Li: izquierda , Ki: clave
  strcpy(temp_fun,izquierda);
  fun_aplicada(temp_fun,clave[i]); //Obtengo en temp_fun: f(Li, Ki)

  //Aplicar XOR: Ri XOR f(Li,Ki)
  fun_xor(temp_xor,temp_fun); //Obtengo en temp_xor: Ri XOR f(Li,Ki)

  //Asignar a Li-1 <- Resultado de Ri XOR f(Li,Ki)
  strcpy(izquierda,temp_xor); //Obtengo en izquierda: Li-1

  //Mostrar valores i+1
  printf("Texto[%i]---> L(%i) = %s\tR(%i) = %s\n", i, i, izquierda, i, derecha);
 }

 printf("Descrifrado: L() = %s\tR() = %s\n", izquierda, derecha);
 printf("%s\n", "--------------------------------------");
}


//Ascii dato[i] + Ascii residuo pwd/17
void fun_aplicada(char dato[],char pwd)
{
 int len_dato;
 len_dato = strlen(dato);
 int pwd_ki;
 pwd_ki= pwd%17;

 int i;
 for (i = 0; i < len_dato; i++)
 {
  dato[i] = dato[i] + pwd_ki;
 }
}


void fun_xor(char dato1[], char dato2[])
{
 int tam;
 tam = strlen(dato1);

 int i;
 for (i = 0; i < tam; i++)
 {
  dato1[i] = dato1[i]^dato2[i];
 }
}

Una ventaja de este modelo es que la función usada no tiene por que se reversible, pudiendo ser todo lo complicada que se desee, esta cualidad permite a los criptografos concentrarse en la seguridad de dicha funcion sabiendo que el proceso de descifrado esta garantizado ya que la propia estructura de la red de Feistel es reversible. Para ello unicamente requiere que se invierta el orden de las subclaves utilizadas.



Enlaces


https://github.com/phaoliop/Programming_C-Cplus/blob/master/C/Cifrado/feistel.c


Referencias