Ir al contenido



Foto

Como usar blowfish de openssl


  • Por favor identifícate para responder
17 respuestas en este tema

#1 axesys

axesys

    Advanced Member

  • Moderadores
  • PipPipPip
  • 640 mensajes
  • LocationLos Mochis

Escrito 28 mayo 2009 - 03:35

Estoy tratando de usar unas funciones de blowfish que vienen en openssl pero me salen carateres raros al final despues de descencriptar.

¿Alguien sabe la manera correcta de usarlas?

Estas son las funciones
http://www.openssl.o...o/blowfish.html

Y este es un código que me encontre modificado:


cpp
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <openssl/blowfish.h>
  5.  
  6. void encrypt(char *inbuf, char *outbuf, int blklen, char *key)
  7. {
  8.   int counter = 0;
  9.   char iv[8];
  10.   BF_KEY keyStruct;
  11.   memset(iv, 0, 8);
  12.   BF_set_key(&keyStruct, strlen(key), key);
  13.   BF_cfb64_encrypt(inbuf, outbuf, blklen, &keyStruct, iv, &counter, BF_ENCRYPT);
  14. }
  15.  
  16. void decrypt(char *inbuf, char *outbuf, int blklen, char *key)
  17. {
  18.   int counter = 0;
  19.   char iv[8];
  20.   BF_KEY keyStruct;
  21.   memset(iv, 0, 8);
  22.   BF_set_key(&keyStruct, strlen(key), key);
  23.   BF_cfb64_encrypt(inbuf, outbuf, blklen, &keyStruct, iv, &counter, BF_DECRYPT);
  24. }
  25.  
  26. int main(void)
  27. {
  28.   char *entrada = malloc(200);
  29.   strcpy(entrada, "Cadena que se va a encriptar para luego desencriptarla");
  30.   char *salida = malloc(200);
  31.   char *result = malloc(200);
  32.   encrypt(entrada, salida, strlen(entrada), "1234567890123456");
  33.   printf("Cadena encriptada=%s\n", salida);
  34.   decrypt(salida, result, strlen(salida), "1234567890123456");
  35.   printf("Cadena desencriptada=%s\n", result);
  36.   return 0;
  37. }



Luego así­ lo compilo y lo ejecuto


delphi
  1. gcc blowfish.c -o blowfish -lssl
  2. ./blowfish


  • 0

#2 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.943 mensajes
  • LocationMadrid - España

Escrito 28 mayo 2009 - 05:14

Nunca he usado blowfish pero me llama la atención una cosa de tu ejemplo:


cpp
  1. encrypt(entrada, salida, strlen(entrada), "1234567890123456");
  2. printf("Cadena encriptada=%s\n", salida);
  3. decrypt(salida, result, strlen(salida), "1234567890123456");
  4. printf("Cadena desencriptada=%s\n", result);



Cuando desencriptas el buffer salida, asumes que es una cadena y pasas como parámetro strlen(salida). Pero salida ya no es una cadena de caracteres.
strlen contará los elementos en salida hasta que encuentre un nulo, y ese nulo o nulos, puede estar en cualquier lugar del buffer salida. Entonces el tamaño estará siempre mal calculado. Corrí­geme si me equivoco.

Saludos.
  • 0

#3 axesys

axesys

    Advanced Member

  • Moderadores
  • PipPipPip
  • 640 mensajes
  • LocationLos Mochis

Escrito 28 mayo 2009 - 06:05

Nunca he usado blowfish pero me llama la atención una cosa de tu ejemplo:


cpp
  1. encrypt(entrada, salida, strlen(entrada), "1234567890123456");
  2. printf("Cadena encriptada=%s\n", salida);
  3. decrypt(salida, result, strlen(salida), "1234567890123456");
  4. printf("Cadena desencriptada=%s\n", result);



Cuando desencriptas el buffer salida, asumes que es una cadena y pasas como parámetro strlen(salida). Pero salida ya no es una cadena de caracteres.
strlen contará los elementos en salida hasta que encuentre un nulo, y ese nulo o nulos, puede estar en cualquier lugar del buffer salida. Entonces el tamaño estará siempre mal calculado. Corrí­geme si me equivoco.

Saludos.


Si tienes razón. ¿No sabes cual serí­a la forma correcta de saber el tamaño?
  • 0

#4 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.943 mensajes
  • LocationMadrid - España

Escrito 29 mayo 2009 - 05:59

...¿No sabes cual serí­a la forma correcta de saber el tamaño?


Applications should use the higher level functions EVP_EncryptInit(3) etc. instead of calling the blowfish functions directly.


En este fragmento de código extraí­do de los ejemplos de openssl podemos ver como se pretende encriptar un texto y escribir el resultado en un archivo. Ese archivo se escribe con la función fwrite y un tamaño outlen calculado:


cpp
  1. int do_crypt(char *outfile)
  2.         {
  3.         unsigned char outbuf[1024];
  4.         int outlen, tmplen;
  5.         /* Bogus key and IV: we'd normally set these from
  6.         * another source.
  7.         */
  8.         unsigned char key[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
  9.         unsigned char iv[] = {1,2,3,4,5,6,7,8};
  10.         char intext[] = "Some Crypto Text";
  11.         EVP_CIPHER_CTX ctx;
  12.         FILE *out;
  13.         EVP_CIPHER_CTX_init(&ctx);
  14.         EVP_EncryptInit_ex(&ctx, EVP_bf_cbc(), NULL, key, iv);
  15.  
  16.         if(!EVP_EncryptUpdate(&ctx, outbuf, &outlen, intext, strlen(intext)))
  17.                 {
  18.                 /* Error */
  19.                 return 0;
  20.                 }
  21.         /* Buffer passed to EVP_EncryptFinal() must be after data just
  22.         * encrypted to avoid overwriting it.
  23.         */
  24.         if(!EVP_EncryptFinal_ex(&ctx, outbuf + outlen, &tmplen))
  25.                 {
  26.                 /* Error */
  27.                 return 0;
  28.                 }
  29.         outlen += tmplen;
  30.         EVP_CIPHER_CTX_cleanup(&ctx);
  31.         /* Need binary mode for fopen because encrypted data is
  32.         * binary data. Also cannot use strlen() on it because
  33.         * it wont be null terminated and may contain embedded
  34.         * nulls.
  35.         */
  36.         out = fopen(outfile, "wb");
  37.         fwrite(outbuf, 1, outlen, out);
  38.         fclose(out);
  39.         return 1;
  40.         }



Saludos.


  • 0

#5 axesys

axesys

    Advanced Member

  • Moderadores
  • PipPipPip
  • 640 mensajes
  • LocationLos Mochis

Escrito 29 mayo 2009 - 10:06

Gracias escafandra. Nomas que al parecer ya no me mete basura cuando desencripto. Ahora en lugar de ponerle tamaño fijo de 200 le asigne directamente la cadena. Aquí­ les pongo como quedo el código.

libblowfish.c


cpp
  1. #include <stdlib.h>
  2. #include <string.h>
  3. #include <openssl/blowfish.h>
  4.  
  5. void encrypt(char *inbuf, char *outbuf)
  6. {
  7.   char *key = "1234567890123456";
  8.   int blklen = strlen(inbuf);
  9.   int counter = 0;
  10.   char iv[8];
  11.   memset(iv, 0, 8);
  12.   BF_KEY keyStruct;
  13.   BF_set_key(&keyStruct, strlen(key), key);
  14.   BF_cfb64_encrypt(inbuf, outbuf, blklen, &keyStruct, iv, &counter, BF_ENCRYPT);
  15. }
  16.  
  17. void decrypt(char *inbuf, char *outbuf)
  18. {
  19.   char *key = "1234567890123456";
  20.   int blklen = strlen(inbuf);
  21.   int counter = 0;
  22.   char iv[8];
  23.   memset(iv, 0, 8);
  24.   BF_KEY keyStruct;
  25.   BF_set_key(&keyStruct, strlen(key), key);
  26.   BF_cfb64_encrypt(inbuf, outbuf, blklen, &keyStruct, iv, &counter, BF_DECRYPT);
  27. }



libblowfish.h


cpp
  1. void encrypt(char *inbuf, char *outbuf);
  2. void decrypt(char *inbuf, char *outbuf);



demo_blowfish.c


cpp
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include "libblowfish.h"
  5.  
  6. int main(void)
  7. {
  8.   char *entrada = "Cadena que se va a encriptar";
  9.   char *salida = malloc(strlen(entrada));
  10.   char *result = malloc(strlen(entrada));
  11.   encrypt(entrada, salida);
  12.   decrypt(salida, result);
  13.   printf("%s\n", result);
  14.   return 0;
  15. }



compilar.sh


delphi
  1. #!/bin/bash
  2. gcc -I. -fPIC -Wall -g -c libblowfish.c
  3. gcc -g -shared -Wl,-soname,libblowfish.so.0 -o libblowfish.so.0.0 libblowfish.o -lssl -lc
  4. cp libblowfish.so.0.0 /usr/local/lib
  5. /sbin/ldconfig -n .
  6. ln -sf libblowfish.so.0 libblowfish.so
  7. gcc -Wall -g -c demo_blowfish.c -o demo_blowfish.o
  8. gcc -g -o demo_blowfish demo_blowfish.o -L. -lblowfish
  9. LD_LIBRARY_PATH="." ./demo_blowfish


  • 0

#6 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.943 mensajes
  • LocationMadrid - España

Escrito 29 mayo 2009 - 02:26

¿Has probado con la cadena original  "Cadena que se va a encriptar para luego desencriptarla" y con otras?
Creo que en blowfish el tamaño del buffer entrada es distinto que el de salida.
Un método de encripación XOR no garantiza que ningún Byte no sea nulo y eso te altera el fin de la cadena, con lo que un strlen no te sirve para medir el tamaño de un bloque encriptado.

Por otro lado creo que deber revisar alguna cosilla:


cpp
  1. char *entrada = "Cadena que se va a encriptar";
  2. char *salida = malloc(strlen(entrada));
  3. char *result = malloc(strlen(entrada));



Te olvidaste reservar espacio para el ultimo carácter nulo de fí­n de cadena y a la larga petará...



cpp
  1. char *entrada = "Cadena que se va a encriptar";
  2. char *salida = malloc(strlen(entrada)+1);
  3. char *result = malloc(strlen(entrada)+1);



Saludos.

  • 0

#7 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.111 mensajes
  • LocationMéxico

Escrito 29 mayo 2009 - 02:31

Muy interesante amigo escafandra, que buen nivel tienes (y)

Salud OS
  • 0

#8 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.943 mensajes
  • LocationMadrid - España

Escrito 29 mayo 2009 - 03:17

Muy interesante amigo escafandra, que buen nivel tienes (y)

Salud OS


Pues gracias por el comentario  :) pero realmente me considero un simple aficionado.  :p
  • 0

#9 axesys

axesys

    Advanced Member

  • Moderadores
  • PipPipPip
  • 640 mensajes
  • LocationLos Mochis

Escrito 02 junio 2009 - 09:44

¿Has probado con la cadena original  "Cadena que se va a encriptar para luego desencriptarla" y con otras?
Creo que en blowfish el tamaño del buffer entrada es distinto que el de salida.
Un método de encripación XOR no garantiza que ningún Byte no sea nulo y eso te altera el fin de la cadena, con lo que un strlen no te sirve para medir el tamaño de un bloque encriptado.



Pues no me a tocado una cadena que me ponga nulos como fin de cadena aún.


Por otro lado creo que deber revisar alguna cosilla:


cpp
  1. char *entrada = "Cadena que se va a encriptar";
  2. char *salida = malloc(strlen(entrada));
  3. char *result = malloc(strlen(entrada));



Te olvidaste reservar espacio para el ultimo carácter nulo de fí­n de cadena y a la larga petará...



cpp
  1. char *entrada = "Cadena que se va a encriptar";
  2. char *salida = malloc(strlen(entrada)+1);
  3. char *result = malloc(strlen(entrada)+1);



Saludos.



Lo que si me paso fue que acabo de pasar a windows el codigo y ya se petatio  :( otra vez mete caracteres raros al final de la cadena desencriptada.
  • 0

#10 axesys

axesys

    Advanced Member

  • Moderadores
  • PipPipPip
  • 640 mensajes
  • LocationLos Mochis

Escrito 02 junio 2009 - 03:16

Ahora cambie el malloc por calloc y parece que ya se arreglo en windows. Aquí­ les pongo como quedo el código.

blowfish.c


cpp
  1. #include <stdlib.h>
  2. #include <string.h>
  3. #include "openssl\blowfish.h"
  4.  
  5. void encrypt(char *inbuf, char *outbuf)
  6. { 
  7.   char *key = "1234567890123456";
  8.   int blklen = strlen(inbuf);
  9.   int counter = 0;
  10.   char iv[8];
  11.   memset(iv, 0, 8);
  12.   BF_KEY keyStruct;
  13.   BF_set_key(&keyStruct, strlen(key), key);
  14.   BF_cfb64_encrypt(inbuf, outbuf, blklen, &keyStruct, iv, &counter, BF_ENCRYPT);
  15. }
  16.  
  17. void decrypt(char *inbuf, char *outbuf)
  18. {
  19.   char *key = "1234567890123456";
  20.   int blklen = strlen(inbuf);
  21.   int counter = 0;
  22.   char iv[8];
  23.   memset(iv, 0, 8);
  24.   BF_KEY keyStruct;
  25.   BF_set_key(&keyStruct, strlen(key), key);
  26.   BF_cfb64_encrypt(inbuf, outbuf, blklen, &keyStruct, iv, &counter, BF_DECRYPT);
  27. }



libblowfish.h


cpp
  1. void encrypt(char *inbuf, char *outbuf);
  2. void decrypt(char *inbuf, char *outbuf);



demo_blowfish.c


cpp
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include "blowfish.h"
  5.  
  6. int main(void)
  7. {
  8.   char* entrada = "Cadena que se va a encriptar";
  9.   char* salida = (char*) calloc(strlen(entrada) + 1, sizeof(char));
  10.   char* result = (char*) calloc(strlen(entrada) + 1, sizeof(char));
  11.   encrypt(entrada, salida);
  12.   decrypt(salida, result);
  13.   printf("%s\n", result);
  14.   free(result); result = NULL;
  15.   free(salida); salida = NULL;
  16.   free(entrada); entrada = NULL;
  17.   return 0;
  18. }



compilar.bat


delphi
  1. gcc -I. -I"C:\Archivos de programa\GnuWin32\include" -Wall -g -c blowfish.c
  2. gcc -g -shared -o blowfish.dll blowfish.o -L./ -leay32
  3. copy blowfish.dll C:\windows\system32
  4. gcc -Wall -g -c demo_blowfish.c -o demo_blowfish.o
  5. gcc -g -o demo_blowfish demo_blowfish.o -L./ -lblowfish
  6. demo_blowfish



Para compilarlos nomas ocupan instalar el MinGW y el OpenSSL
  • 0

#11 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.943 mensajes
  • LocationMadrid - España

Escrito 02 junio 2009 - 03:49

La forma de como reserves memoria, calloc o malloc no influye, es el tamaño del buffer. En tu nuevo código reservas el espacio de la cadena original, lo que te garantiza que al desencriptar tendrás el espacio apropiado.

Saludos.
  • 0

#12 axesys

axesys

    Advanced Member

  • Moderadores
  • PipPipPip
  • 640 mensajes
  • LocationLos Mochis

Escrito 02 junio 2009 - 06:39

La forma de como reserves memoria, calloc o malloc no influye, es el tamaño del buffer. En tu nuevo código reservas el espacio de la cadena original, lo que te garantiza que al desencriptar tendrás el espacio apropiado.

Saludos.


Gracias escafandra, hice la prueba quitando el + 1 y salen otra vez caracteres raros al final de la cadena desencriptada. Supongo que por ahí­ iba el problema de que no reservaba suficiente memoria.


Saludos
  • 0

#13 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.943 mensajes
  • LocationMadrid - España

Escrito 03 junio 2009 - 12:30

Si el tema son los tamaños de los buffers y los códigos de fin de cadena (cero). Un detalle que debes tener en cuenta es que ese +1, que es el espacio para el  cero final, debes considerarlo en la encriptación de una de estas dos formas:


1.- Lo encriptas también, es decir en la función de encriptación y des encriptación usas el buffer completo: tamaño = strlen(Cadena)+1

2.- No lo encriptas pero lo añades al final, esto es importante sobre todo al desencriptar, pues marca el final de la cadena desencriptada. Piensa que en C cuando reservas memoria ese bloque tiene valores aleatorios.

Personalmente pienso que es mejor encriptar el cero final, al fin y al cabo forma parte del buffer reservado.

Saludos.

PD: Aunque no tan segura como blowfish, aquí­ deje una rutina que escribí­ para encriptar bloques con un método simétrico XOR.
  • 0

#14 axesys

axesys

    Advanced Member

  • Moderadores
  • PipPipPip
  • 640 mensajes
  • LocationLos Mochis

Escrito 03 junio 2009 - 11:01

Hola escafandra, yo creo que ya me paso el problema que comentabas de los nulos en medio de la cadena encriptada.

Primero encripto la cadena de 161 caracteres "ter1000000000000000000000000000001111t111111111t11111111111o111111100000000000000098111111111111111.100202/06/200900000000000000000001111111111111000000000012345"
Y me regresa una cadena de solo 84 caracteres que al desencriptarla también me regresa solo los primeros 84 caracteres de la cadena original.

Si cambio el caracter 85 que es un 1 por un 2 entonces si regresa los 161 caracteres encriptados.

¿No sabes de alguna solución para esto?


Saludos
  • 0

#15 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.943 mensajes
  • LocationMadrid - España

Escrito 03 junio 2009 - 11:13

¿Cual es el último código que has utilizado en esta prueba?.

Saludos.
  • 0

#16 axesys

axesys

    Advanced Member

  • Moderadores
  • PipPipPip
  • 640 mensajes
  • LocationLos Mochis

Escrito 03 junio 2009 - 12:25

El mismo del mensaje 9 nomas cambia en el demo_blowfish.c "Cadena que se va a encriptar" por "ter1000000000000000000000000000001111t111111111t11111111111o111111100000000000000098111111111111111.100202/06/200900000000000000000001111111111111000000000012345"


Saludos
  • 0

#17 escafandra

escafandra

    Advanced Member

  • Moderadores
  • PipPipPip
  • 3.943 mensajes
  • LocationMadrid - España

Escrito 03 junio 2009 - 12:35

Pues la solución está por pasar el parámetro tamaño del buffer en tus funciones de encriptación:



cpp
  1. void encrypt(char *inbuf, char *outbuf, int blklen)
  2. { 
  3.   char *key = "1234567890123456";
  4.   int counter = 0;
  5.   char iv[8];
  6.   memset(iv, 0, 8);
  7.   BF_KEY keyStruct;
  8.   BF_set_key(&keyStruct, strlen(key), key);
  9.   BF_cfb64_encrypt(inbuf, outbuf, blklen, &keyStruct, iv, &counter, BF_ENCRYPT);
  10. }
  11.  
  12. void decrypt(char *inbuf, char *outbuf, int blklen)
  13. {
  14.   char *key = "1234567890123456";
  15.   int counter = 0;
  16.   char iv[8];
  17.   memset(iv, 0, 8);
  18.   BF_KEY keyStruct;
  19.   BF_set_key(&keyStruct, strlen(key), key);
  20.   BF_cfb64_encrypt(inbuf, outbuf, blklen, &keyStruct, iv, &counter, BF_DECRYPT);
  21. }
  22.  
  23. int main(void)
  24. {
  25.   char* entrada = "Cadena que se va a encriptar";
  26.   int size = strlen(entrada) + 1;
  27.   char* salida = (char*) calloc(size , sizeof(char));
  28.   char* result = (char*) calloc(size , sizeof(char));
  29.   encrypt(entrada, salida, size);
  30.   decrypt(salida, result, size);
  31.   printf("%s\n", result);
  32.   free(result); result = NULL;
  33.   free(salida); salida = NULL;
  34.   free(entrada); entrada = NULL;
  35.   return 0;
  36. }



Saludos.
  • 0

#18 axesys

axesys

    Advanced Member

  • Moderadores
  • PipPipPip
  • 640 mensajes
  • LocationLos Mochis

Escrito 03 junio 2009 - 03:52

Gracias escafandra ya funciono, como siempre la cadena que ocupamos encriptar y desencriptar es de 161 caracteres se lo puse fijo.



cpp
  1. #include <stdlib.h>
  2. #include <string.h>
  3. #include "openssl\blowfish.h"
  4.  
  5. char* encrypt(char *inbuf, char *outbuf)
  6. { 
  7.   char *key = "1234567890123456";
  8.   int counter = 0;
  9.   char iv[8];
  10.   memset(iv, 0, 8);
  11.   BF_KEY keyStruct;
  12.   BF_set_key(&keyStruct, strlen(key), key);
  13.   BF_cfb64_encrypt(inbuf, outbuf, 161, &keyStruct, iv, &counter, BF_ENCRYPT);
  14.   return outbuf;
  15. }
  16.  
  17. char* decrypt(char *inbuf, char *outbuf)
  18. {
  19.   char *key = "1234567890123456";
  20.   int counter = 0;
  21.   char iv[8];
  22.   memset(iv, 0, 8);
  23.   BF_KEY keyStruct;
  24.   BF_set_key(&keyStruct, strlen(key), key);
  25.   BF_cfb64_encrypt(inbuf, outbuf, 161, &keyStruct, iv, &counter, BF_DECRYPT);
  26.   return outbuf;
  27. }




Saludos
  • 0