domingo, 23 de marzo de 2014

Algoritmo de Desencriptado en C

Aquí os traigo otros de los ejercicios en C que nos han puesto. Un algoritmo que desencripte. Aquí dos archivos encriptados para probar que desencripte: ARCHIVO1 ARCHIVO2

El enunciado es el siguiente:

Un algoritmo de cifrado por bloques opera con bloques de 64 bits y una clave de 128
bits siguiendo el siguiente procedimiento.

Para cada bloque de 64 bits (unsigned long v[2]), sea la clave k (unsigned long
k[4]), y delta una constante igual a 0x9e3779b9:

 Inicializar sum a 0xC6EF3720

Repetir 32 veces:
 Restar a v[1] la aplicación del operador XOR (^) a
(v[0] desplazado a la izquierda 4 bits +k[2]),
(v[0] + sum) y
 (v[0] desplazado a la derecha 5 bits)+k[3]

Restar a v[0] la aplicación del operador XOR (^) a:
(v[1] desplazado a la izquierda 4 bits + k[0])
(v[1]+ sum) y
(v[1] desplazado a la derecha 5 bits)+k[1]

 Restar a sum el valor de delta.

Al final de las 32 iteraciones, se tendrá en v el valor desencriptado de los 64 bits.

Realizar un programa en C que cargue en memoria dinámica el contenido de un fichero
encriptado, realice su desencriptado siguiendo el procedimiento descrito y lo almacene
en un fichero de salida (recordar liberar la memoria dinámica al final). Tanto el nombre
del fichero de entrada como el del fichero de salida son indicados como argumentos del
programa en la línea de comandos.

Como el tamaño del fichero original no tiene porqué ser múltiplo de 8 y el algoritmo de
desencriptado trabaja con bloques de 8 bytes (64 bits) hay que tener en cuenta las
siguientes indicaciones:
- Al comienzo del fichero encriptado se encuentra almacenado (unsigned long)
el tamaño del fichero original desencriptado. Este tamaño no hay que
almacenarlo en memoria dinámica.
- Al hacer el encriptado, si el tamaño del fichero original no era múltiplo de 8, se
tiene al final un bloque incompleto para aplicar el cifrado, por lo que
artificialmente se completa hasta tener 8 bytes. Estos valores de relleno están
almacenados también en el fichero encriptado, y deben también ser
desencriptados, pero no deben escribirse en el fichero de salida.
Por ejemplo, si el fichero original ocupa 30 bytes, al hacer el encriptado se tuvieron que
utilizar 32 bytes, esto es, se pusieron 2 valores de relleno. La longitud total del fichero
encriptado es 4 (almacenamiento de la longitud del fichero encriptado) + 30 + 2
(posiciones de relleno), esto es 36 bytes. Al hacer el desencriptado, se hará de 32 bytes,
pero sólo se escriben 30 en el fichero de salida.

Para realizar el desencriptado se recomienda definir una función con la siguiente
cabecera:
void decrypt(unsigned long* v, unsigned long* k);

donde v es el array de 2 unsigned long que se va a desencriptar y k es la clave
consistente en un array de 4 unsigned long con los siguientes valores: {128, 129,
130, 131}.

Se recomienda utilizar las siguientes funciones de C: fopen, fread, fwrite, fclose,
malloc, free y memcpy.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void decrypt(unsigned long* v, unsigned long* k){
 unsigned long sum = 0xC6EF3720;
 unsigned long delta = 0x9E3779B9;
 unsigned i;
 for(i=1; i <= 32; i++){
  v[1] = v[1]- (((v[0] << 4)+k[2])^(v[0] + sum)^((v[0] >> 5)+k[3]));
  v[0] = v[0] - (((v[1] << 4)+ k[0]) ^(v[1]+sum)^((v[1] >> 5)+ k[1]));
  sum = sum - delta;
 }
}

int main(int argc,char *argv[]) {
 FILE * f;
 FILE * salida;
 unsigned long tamsalida;
 unsigned long tamentrada;
 unsigned long v[2];
 unsigned long k[4] = {128, 129, 130, 131};
 //Si no usáramos argv...
 //char * ficheroEntrada = "imgno8.enc";
 //char * ficheroSalida = "salida.png";
 char * datos;
 int i, aux;


 // 1 - Leer el tamaño del fichero original que está al comienzo del fichero encriptado


 if((f = fopen(argv[1], "rb")) == NULL){
  printf("ERROR. El fichero no existe.");
  exit(-1);
 }

 fread(&tamsalida, sizeof(long), 1, f);

 //printf("Tamaño del fichero original: %ld \n", tamsalida);




 // 2 Calcular el tamaño de los datos
 if(tamsalida%8){
  tamentrada = tamsalida +(8-(tamsalida % 8));
 }else{//tamaño multiplo de ocho, no añadimos nada
  tamentrada = tamsalida;
 }
 //printf("Tamaño de los datos a desencriptar: %ld \n", tamentrada);


 // 3 - Almacenar datos en memoria

 datos = (char *) malloc(tamentrada * sizeof(char));

 fread(datos, sizeof(char), tamentrada, f);
 fclose(f);

 // 4 - Descrifrar y escribir
 char * ptr = datos;
 salida = fopen(argv[2], "wb");
 //BUCLE que meta lo que haya en v en el fichero salida. (para recorrer los datos usamos ptr)
 aux = tamsalida/8;

 for(i = 0; i < aux; i++){
  memcpy(v,ptr,8);
  decrypt(v,k);
  fwrite(v, sizeof(char), 8, salida);
  ptr = ptr + 8;
 }
 // fin del bucle
 if (tamsalida % 8 ) {

  memcpy(v,ptr,8);
  decrypt(v,k);
  fwrite(v,sizeof(char),tamsalida% 8,salida);
 }

 free(datos);

 fclose(salida);


 return EXIT_SUCCESS;
}


Os dejo también el código para descargar.

Un saludo (:

No hay comentarios:

Publicar un comentario