Problema con cifrado AES

Iniciado por Kaxperday, 30 Octubre 2015, 14:18 PM

0 Miembros y 1 Visitante están viendo este tema.

Kaxperday

Hola de nuevo, tengo un archivo donde introduzco montones de datos cifrados de uno en uno, y luego lo descifro a la vez todo y muestro una cadena.

El texto descifrado está casi bien, pero muestra basura en el texto descifrado del principio de los montones.

"hoy hace un buen dia" -> cifro : "isewug0uwe0igj" -> al descifrar "iqh39h buen dia".

Esto pasa con todos los montones de datos que descifro menos con el primero que se mantiene intacto, os dejo el código para que me podáis ayudar:

Clase que cifra, la clase "bytes" es un typedef tuple<u_char*,int> contenido y tamaño de los datos cifrados o descifrados.

Código (cpp) [Seleccionar]
bool encriptador_AES::inicializar_AES(string _contraseña, int _rondas)
{
u_char key[32], iv[32];
u_int salto[2] = { MINIMO_SALTO, MAXIMO_SALTO };
if (EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha1(), (u_char*)&salto, (u_char*)_contraseña.c_str(), _contraseña.length(), _rondas, key, iv) != 32)
return false;
EVP_CIPHER_CTX_init(&en);
EVP_EncryptInit_ex(&en, EVP_aes_256_cbc(), NULL, key, iv);
EVP_CIPHER_CTX_init(&de);
EVP_DecryptInit_ex(&de, EVP_aes_256_cbc(), NULL, key, iv);
return true;
}

bytes encriptador_AES::encriptar_AES(u_char *_entrada, int _tamaño)
{
int c_len = _tamaño + AES_BLOCK_SIZE, f_len = 0;
u_char *salida = (u_char*)malloc(c_len);
EVP_EncryptInit_ex(&en, NULL, NULL, NULL, NULL);
EVP_EncryptUpdate(&en, salida, &c_len, _entrada, _tamaño);
EVP_EncryptFinal_ex(&en, salida + c_len, &f_len);
return bytes(salida, c_len + f_len);
}

string encriptador_AES::desencriptar_AES(u_char *_entrada, int _tamaño)
{
int p_len = _tamaño, f_len = 0;
u_char *salida = (u_char*)malloc(p_len);
EVP_DecryptInit_ex(&de, NULL, NULL, NULL, NULL);
EVP_DecryptUpdate(&de, salida, &p_len, _entrada, _tamaño);
EVP_DecryptFinal_ex(&de, salida + p_len, &f_len);
string ret;
for (int i = 0; i < p_len + f_len; i++) ret += salida[i];
delete salida;
return ret;
}


Clase almacen que escribe en un fichero en binario los datos cifrados y los lee y los descifra:

Código (cpp) [Seleccionar]
almacen::almacen(string _directorio)
{
directorio = _directorio;
cifrador.inicializar_AES(CLAVE_AES, 5);
}

void almacen::escribir_cifrado(bytes _datos)
{
ofstream archivo;
archivo.open(directorio, ofstream::app | ofstream::binary);
_datos = cifrador.encriptar_AES(get<CONTENIDO>(_datos), get<TAMAÑO>(_datos));
archivo.write((char*)get<CONTENIDO>(_datos), get<TAMAÑO>(_datos));
archivo.close();
}

string almacen::leer_descifrado()
{
//probar que vaya parte a parte mejor, en vez de entera.
ifstream archivo;
archivo.open(directorio, ifstream::in | ifstream::binary);
archivo.seekg(0, ifstream::end);
streampos tamaño = archivo.tellg();
char *contenido = new char[tamaño]();
archivo.seekg(0, ifstream::beg);
archivo.read(contenido, tamaño);
archivo.close();
string ret = cifrador.desencriptar_AES((u_char*)contenido, tamaño);
delete contenido;
return ret;
}


En una función introduzco el texto para que sea cifrado de esta manera, siendo contenido un string con los datos en texto plano:

_archivo.escribir_cifrado(bytes((u_char*)contenido.c_str(), contenido.length()));

De esta manera se escriben los datos cifrados en el archivo.

Pasado un rato abro el programa y descifro:

Código (cpp) [Seleccionar]
int main(){
almacen o("C:\\Users\\username\\Desktop\\PRUEBA.txt");
cout << o.leer_descifrado();
}


Me muestra el primer bloque entero, y los demás parcialmente enteros, se come el principio de cada bloque y muestra basura, ¿quizás deba de añadir tras añadir un bloque cifrado al archivo?, nose.

Os dejo este link, donde me he basado para implementar el cifrado AES:

http://snipplr.com/view/83706/aes-encryptiondecryption-demo-program-using-openssl-evp-apis/

Muchas gracias y un saludo, se agradece la ayuda, cualquier cosa que necesitéis la subiré.

Ejemplo de salida descifrada:

CitarFecha: Fri Oct 30 14:19:35 2015
Proceso: explorer.exe
Pesta±a: Program Manager
Contenido: hjghjghjgh ║;!=úìõ│¡Ð╣ã830 14:19:37 2015
Proceso: cmd.exe
Pesta±a: C:\WINDOWS\system32\cmd.exe
Contenido: ghjghjghjghÍ 3'KÏü¢sCbÌûhð30 14:19:38 2015
Proceso: explorer.exe
Pesta±a: Program Manager
Contenido: ghjghjgh

Como véis el primer bloque está entero, el segundo muesra basura en vez de mostrar "\nFecha: Fri Oct 30 ", así ocurre con el resto de bloques posteriores.

¿Puede ser fallo al escribir y leer? ¿o fallo al cifrar y descifrar?
Cuando el poder económico parasita al político ningún partido ni dictador podrá liberarnos de él. Se reserva el 99% ese poder.

engel lex

el bloque que sale erróneo es de longitud fija? o varía?

siempre sigues este patrón o similar?

ghjghjgh
El problema con la sociedad actualmente radica en que todos creen que tienen el derecho de tener una opinión, y que esa opinión sea validada por todos, cuando lo correcto es que todos tengan derecho a una opinión, siempre y cuando esa opinión pueda ser ignorada, cuestionada, e incluso ser sujeta a burla, particularmente cuando no tiene sentido alguno.

Kaxperday

#2
Es de longitud variable, yo tengo una cadena que quiero meter en mi archivo cifrada, lo hago de esta forma:

_archivo.escribir_cifrado(bytes((u_char*)contenido.c_str(), contenido.length()));

La variable contenido suele tener esta forma:

CitarFecha: Fri Oct 30 14:19:35 2015
Proceso: explorer.exe
Pesta±a: Program Manager
Contenido: hjghjghjgh

Donde "hjhjhjhjhj", son las teclas que pulso, la fecha el momento que las pulso, el proceso donde las pulso y el nombre de pestaña donde las pulso, todos esos datos están en la string contenido, entonces los envió al archivo através del método "escribir_cifrado", lo paso a u_char* y el tamaño.

Si pulso otras teclas, serán las que pulse las que aparezcan al final de contenido.

El programa es como un keyloguer que cuando cambiamos de ventana guarda los datos que capturo en ella y los escribe cifrados en el archivo.

Así pues cada vez que cambio de pestaña y escribo en otra, se mete un nuevo monton de datos cifrado al archivo, tras hacer unas pruebas y guardar 3 o 4 montones de datos en el archivo cierro el programa, y pruebo a desencriptarlo.

Pero la salida tiene esos errores que he mostrado antes, muestra basura al descifrar el comienzo de los bloques, excepto del primero que no lo hace.

Saludos y gracias.

Iré añadiendo nueva info conforme vaya haciendo más pruebas, un saludo.

Edito: Creo que no es problema del cifrado sino de escritura en el archivo, al escribir un monton detrás de otro creo que algo se hace mal, el método write será lo correcto? o me paso a FILE...?.
Cuando el poder económico parasita al político ningún partido ni dictador podrá liberarnos de él. Se reserva el 99% ese poder.

Kaxperday

#3
Bueno, tras leer y seguir haciendo comprobaciones el problema estaba en EVP_DecryptUpdate y que soy todo un principiante en esto, ahí lo que ponía era todo lo que leía del archivo (todos los bloques con distintos tamaños que incluí), y el tamaño del archivo (tamaño de los bytes de los bloques), el problema está en que tengo que ir metiendo bloque a bloque.

La solución pasa por meter siempre un bloque del mismo tamaño y si son muchos datos meter más bloques (por si no entran), luego sería leer el archivo dividir entre el tamaño fijo del bloque e ir descifrando bloque a bloque y lo tendríamos.

El error era garrafal, buscaré a a ver como puedo cifrar siempre tomando el mismo tamaño. E ire uno a uno.

Saludos.

Edito: Para interesados sobre como solucioné el problema:

https://xkcd.com/323/


Cuando el poder económico parasita al político ningún partido ni dictador podrá liberarnos de él. Se reserva el 99% ese poder.