Modo de Criptografia AES CTR 256 de operação no OpenSSL

Im novo para OpenSSL, Alguém pode me dar uma dica sobre como inicializar o modo CTR AES de um arquivo C. Eu sei que esta é a assinatura do método, mas estou tendo problemas com os parâmetros, não há muita documentação nem um exemplo claro de como fazer uma criptografia simples. Eu apreciaria se alguém pudesse exemplificar uma chamada para esse método. Desde já, obrigado!

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); 

Oi Caf Eu realmente aprecio sua resposta rápida, tem sido realmente útil e, definitivamente, o melhor exemplo que encontrei na web. Eu estou tentando abrir um arquivo com comprimento indeterminado, criptografá-lo e escrever outro arquivo com o texto cifrado gerado, abra o arquivo cifrado e recuperar o texto sem formatação. Eu preciso usar um arquivo de uma quantidade considerável de MB porque eu gostaria de comparar o desempenho da CPU. No entanto, eu ainda estou tendo um problema ao descriptografar. De alguma forma, quando descriptografar arquivos txt consideráveis ​​(1504KB), ele não irá descriptografá-lo completo, e eu recebo metade dele em texto simples e a outra metade ainda é cifrada. Acho que isso pode estar relacionado ao tamanho do iv ou ao modo como estou chamando o contador. Aqui está o que eu tenho até agora:

 #include  #include  #include  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 function de criptografia e descriptografia é chamada em execuções diferentes, então tudo é inicializado sempre com os mesmos valores. Obrigado novamente pelas dicas que você pode me fornecer com antecedência e Atenciosamente !!!

Normalmente, você terá a intenção de chamar AES_ctr128_encrypt() repetidamente para enviar várias mensagens com a mesma chave e IV, e um contador incremental. Isso significa que você precisa manter o controle dos valores ‘ivec’, ‘num’ e ‘ecount’ entre as chamadas – portanto, crie uma struct para mantê-los e uma function de boot:

 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); } 

Agora, quando você começar a se comunicar com o destino, precisará gerar um IV para usar e inicializar o contador:

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

Você precisará enviar o byte IV para o destino. Você também precisará inicializar um AES_KEY dos seus bytes-chave brutos:

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

Agora você pode começar a criptografar os dados e enviá-los para o destino, com chamadas repetidas para AES_ctr128_encrypt() assim:

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

( msg_in é um ponteiro para um buffer contendo a mensagem de texto simples, msg_out é um ponteiro para um buffer onde a mensagem criptografada deve ir, e msg_len é o tamanho da mensagem).

Descriptografia é exatamente o mesmo, exceto que você não gera o IV com RAND_bytes() – em vez disso, você pega o valor dado a você pelo outro lado.

Importante:

  1. Não chame init_ctr() mais de uma vez durante o processo de criptografia. O contador e o IV devem ser inicializados apenas uma vez antes do início da criptografia.

  2. Em nenhuma circunstância, ser tentado a obter o IV em qualquer lugar que não seja de RAND_bytes() no lado da criptografia. Não o defina como um valor fixo; não use uma function hash; não use o nome do destinatário; não leia do disco. Gere-o com RAND_bytes() e envie-o para o destino. Sempre que você começar com um contador zero, você deve começar com um IV completamente novo que você nunca usou antes.

  3. Se for possível que você esteja enviando 2 ** 64 bytes sem alterar a chave IV e / ou, você precisará testar o transbordamento do contador.

  4. Não omita a verificação de erros. Se uma function falhar e você a ignorar, é bem possível (mesmo provável) que seu sistema pareça estar funcionando normalmente, mas na verdade estará operando de forma completamente insegura.

Parece que o problema básico com o seu programa de teste é que os valores de modo das chamadas de fopen não estão corretos. Eu acho que você precisa mudar suas chamadas fopen em criptografar para isso:

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

E os que estão descriptografados para:

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

Uma outra coisa que vale a pena ressaltar é que o ckey provavelmente deve ser declarado como um buffer de 32 bytes (256 bits). É verdade que a criptografia de 128 bits usa apenas 16 bytes dos dados da chave. Mas a function OpenSSL AES_set_encrypt_key (pelo menos na versão que estou usando) lê 32 bytes desse buffer. Ele usa apenas o número apropriado de bytes, mas a leitura ocorre. Isso significa que, se o buffer tiver apenas 16 bytes e terminar no final de uma página adjacente a uma página não legível na memory, isso resultaria em uma violação de access.

Ah, e eu notei que há uma chamada estranha para free lá. O free(buffer); chamada não é válida porque o buffer nunca foi alocado. Eu percebo que seu código é apenas um teste simples, mas … bem, nós somos programadores e não podemos nos ajudar.

    Intereting Posts