Soy nuevo en OpenSSL, ¿alguien Puede darme una pista de cómo inicializar AES CTR de un modo C archivo. Sé que esto es el de los métodos de firma, pero estoy teniendo problemas con los parámetros, no hay muchos documentación ni un claro ejemplo de cómo hacer una simple cifrado. Agradecería si alguien pudiera ejemplificar una llamada a este método. Gracias de antemano!

void AES_ctr128_encrypt(const unsigned char *in, unsigned char *out,
    const unsigned long length, const AES_KEY *key,
    unsigned char ivec[AES_BLOCK_SIZE],
    unsigned char ecount_buf[AES_BLOCK_SIZE],
    unsigned int *num);

Hola Caf realmente agradezco su rápida respuesta ha sido realmente útil, y defenetly el mejor ejemplo que he encontrado en la web. Estoy tratando de abrir un archivo con longitud indeterminada, cifrar y escribir otro archivo con el texto cifrado generada, a continuación, abra el cifrado de archivos y recuperar el texto sin formato. Necesito usar un archivo de una considerable cantidad de MB porque me gustaría comparar el rendimiento de la CPU. Sin embargo todavía estoy teniendo un problema a la hora de descifrar. De alguna manera cuando el descifrado de un considerable archivos txt (1504KB)no lo puedo descifrar por completo, y me sale la mitad de ella en texto plano y la otra mitad todavía cifrado. Creo que esto podría estar relacionado con el tamaño de la iv o la forma en que estoy llamando al contador. Aquí es lo que tengo hasta ahora:

#include <openssl/aes.h>
#include <stdio.h>
#include <string.h>
struct ctr_state { 
unsigned char ivec[16];   
unsigned int num; 
unsigned char ecount[16]; 
}; 
FILE *fp;
FILE *rp;
FILE *op;
size_t count;   
char * buffer; 
AES_KEY key; 
int bytes_read, bytes_written;   
unsigned char indata[AES_BLOCK_SIZE]; 
unsigned char outdata[AES_BLOCK_SIZE];  
unsigned char ckey[] =  "thiskeyisverybad"; //It is 128bits though..
unsigned char iv[8] = {0};//This should be generated by RAND_Bytes I will take into    consideration your previous post
struct ctr_state state;   
int init_ctr(struct ctr_state *state, const unsigned char iv[8]){     
state->num = 0; 
memset(state->ecount, 0, 16);      
memset(state->ivec + 8, 0, 8);  
memcpy(state->ivec, iv, 8); 
} 
void encrypt(){ 
//Opening files where text plain text is read and ciphertext stored      
fp=fopen("input.txt","a+b");
op=fopen("output.txt","w");
if (fp==NULL) {fputs ("File error",stderr); exit (1);}   
if (op==NULL) {fputs ("File error",stderr); exit (1);}      
//Initializing the encryption KEY
AES_set_encrypt_key(ckey, 128, &key); 
//Encrypting Blocks of 16 bytes and writing the output.txt with ciphertext  
while (1) {     
init_ctr(&state, iv); //Counter call
bytes_read = fread(indata, 1, AES_BLOCK_SIZE, fp); 
AES_ctr128_encrypt(indata, outdata, bytes_read, &key, state.ivec, state.ecount, &state.num);    
bytes_written = fwrite(outdata, 1, bytes_read, op); 
if (bytes_read < AES_BLOCK_SIZE) 
break; 
}   
fclose (fp); 
fclose (op);
free (buffer); 
}
void decrypt(){
//Opening files where text cipher text is read and the plaintext recovered         
rp=fopen("recovered.txt","w");
op=fopen("output.txt","a+b");
if (rp==NULL) {fputs ("File error",stderr); exit (1);}   
if (op==NULL) {fputs ("File error",stderr); exit (1);} 
//Initializing the encryption KEY
AES_set_encrypt_key(ckey, 128, &key); 
//Encrypting Blocks of 16 bytes and writing the output.txt with ciphertext   
while (1) {     
init_ctr(&state, iv);//Counter call
bytes_read = fread(indata, 1, AES_BLOCK_SIZE, op);  
AES_ctr128_encrypt(indata, outdata, bytes_read, &key, state.ivec, state.ecount, &state.num); 
bytes_written = fwrite(outdata, 1, bytes_read, rp); 
if (bytes_read < AES_BLOCK_SIZE) 
break; 
}   
fclose (rp); 
fclose (op);
free (buffer); 
}
int main(int argc, char *argv[]){  
encrypt();  
//decrypt(); 
system("PAUSE");  
return 0;
}

Cada cifrar y descifrar la función de llamada en diferentes carreras, así que todo se inicializa siempre con los mismos valores. Gracias de nuevo por los consejos me puedes proporcionar por adelantado & Saludos!!!

  • Su problema es que son reinitialising el contador después de cada bloque. Esto está mal – mover el init_ctr() llamar fuera de la while() bucles en el cifrado y el descifrado. indata y outdata también no tiene que ser de AES_BLOCK_SIZE de longitud – que puede ser considerablemente más grande.
  • Usted no debe usar AES_encrypt y amigos. Eso es un solo de software de aplicación, por lo que no podrán disfrutar de soporte de hardware, como AES-NI. Usted debe estar utilizando EVP_* funciones. Consulte EVP el Cifrado y Descifrado Simétrico en el OpenSSL wiki. De hecho, usted probablemente debería ser el uso de cifrado autenticado porque proporciona confidencialidad y autenticidad. Consulte EVP Autenticada de Cifrado y Descifrado en el OpenSSL wiki.
  • Si utiliza el EVP_* funciones, los sistemas de cifrado de interés son EVP_aes_128_ctr, EVP_aes_192_ctr y EVP_aes_256_ctr.
InformationsquelleAutor Bartzilla | 2010-06-29

2 Comentarios

  1. 28

    Por lo general, deberá ser con la intención de llamar AES_ctr128_encrypt() repetidamente para enviar varios mensajes con la misma clave y IV, y un contador incremental. Esto significa que usted necesita para mantener un seguimiento de la ‘ivec’, ‘num’ y ‘ecount’ valores entre llamadas – para crear un struct la celebración de estos, y una función de inicialización:

    struct ctr_state {
    unsigned char ivec[16];  /* ivec[0..7] is the IV, ivec[8..15] is the big-endian counter */
    unsigned int num;
    unsigned char ecount[16];
    };
    int init_ctr(struct ctr_state *state, const unsigned char iv[8])
    {
    /* aes_ctr128_encrypt requires 'num' and 'ecount' set to zero on the
    * first call. */
    state->num = 0;
    memset(state->ecount, 0, 16);
    /* Initialise counter in 'ivec' to 0 */
    memset(state->ivec + 8, 0, 8);
    /* Copy IV into 'ivec' */
    memcpy(state->ivec, iv, 8);
    }

    Ahora, cuando se inicia la comunicación con el destino, necesita generar una vía INTRAVENOSA para el uso y inicializar el contador:

    unsigned char iv[8];
    struct ctr_state state;
    if (!RAND_bytes(iv, 8))
    /* Handle the error */;
    init_ctr(&state, iv);

    Entonces usted tendrá que enviar el byte de 8 IV del destino. Usted también tendrá que establecer una AES_KEY de su prima-clave bytes:

    AES_KEY aes_key;
    if (!AES_set_encrypt_key(key, 128, &aes_key))
    /* Handle the error */;

    Ahora puede iniciar el cifrado de los datos y su envío a la de destino, con repetidas llamadas a AES_ctr128_encrypt() como este:

    if (!AES_ctr128_encrypt(msg_in, msg_out, msg_len, &aes_key, state->ivec, state->ecount, &state->num))
    /* Handle the error */;

    (msg_in es un puntero a un buffer que contiene el mensaje de texto sin formato, msg_out es un puntero a un buffer donde el mensaje cifrado debe ir, y msg_len es la longitud del mensaje).

    De descifrado es exactamente el mismo, excepto que no generan el IV con RAND_bytes() – en su lugar, toma el valor dado a usted por el otro lado.

    Importante:

    1. Hacer no llamada init_ctr() más de una vez durante el proceso de cifrado. El contador y IV deben ser inicializadas sólo una vez antes del inicio de cifrado.

    2. Bajo ninguna circunstancia ser tentado a la IV en otro lugar que de RAND_bytes() en el cifrado de lado. No se establece en un valor fijo; no utilizar una función hash; no utilizar el nombre del destinatario; no leer desde el disco. Generar con RAND_bytes() y enviarlo al destino. Cada vez que usted comienza con un cero contador, usted debe empezar con un completamente nuevo IV que usted nunca ha usado antes.

    3. Si es del todo posible que usted va a enviar 2**64 bytes sin cambiar el IV y/o clave, usted tendrá que probar para el contador de desbordamiento.

    4. No omitir la comprobación de errores. Si la función falla y usted lo ignora, es muy posible (incluso probable) que el sistema parece estar funcionando normalmente, pero en realidad ser operativo completamente inseguro.

    • Permítanme añadir un detalle que se me escapó cuando he usado este: el num argumento es el número de bytes en un bloque en el que están, no el contador. Si el cifrado de los paquetes (por ejemplo), siempre en conjunto estado->num a cero y poner el contador en el alta de los bytes de iv.
    • Elkins: de Hecho – usted puede tratar num y ecount como opaco estado interno de OpenSSL CTR aplicación. En la mayoría de los casos no debe ser necesario modificar directamente de ellos.
  2. 2

    Parece que el problema básico con el programa de la prueba es que el modo de los valores de la fopen llamadas no es la correcta. Creo que usted necesita para cambiar su fopen llamadas en cifrar a este:

    fp=fopen("input.txt","rb");
    op=fopen("output.txt","wb");

    Y los de descifrar a:

    rp=fopen("recovered.txt","wb");
    op=fopen("output.txt","rb");

    Otra cosa que vale la pena destacar es que ckey probablemente debería ser declarado como una de 32 bytes (256 bits) de búfer. Es cierto que el cifrado de 128 bits sólo utiliza los 16 bytes de los datos de la clave. Pero el OpenSSL función AES_set_encrypt_key (al menos en la versión que estoy usando) lee 32 bytes de ese buffer. Solo se utiliza el número de bytes, pero la lectura no se producen. Eso significa que si el buffer es sólo de 16 bytes y sucede final al final de una página que está adyacente a un que no sea legible página en la memoria, que resulte en una violación de acceso.

    Oh – y me di cuenta de que hay una extraña llamada a free allí. El free(buffer); llamada no es válido, ya que búfer nunca fue asignado. Me doy cuenta de que el código es sólo una prueba simple, pero … bueno, que son los programadores y no podemos ayudarnos a nosotros mismos.

Dejar respuesta

Please enter your comment!
Please enter your name here