Search code examples
caesmcrypt

AES encryption result only part of data are correct (using mcrypt lib)


I download a sample code of AES encryption from https://gist.github.com/2436364 I modified part of the source code to meet my project requirement as below:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mcrypt.h>
#include <math.h>
#include <stdint.h>

int encrypt(void* buffer, int buffer_len, char* IV, char* key, int key_len){
  MCRYPT td = mcrypt_module_open("rijndael-128", NULL, "cbc", NULL);
  int blocksize = mcrypt_enc_get_block_size(td);
  if( buffer_len % blocksize != 0 )
    return 1;

  mcrypt_generic_init(td, key, key_len, IV);
  mcrypt_generic(td, buffer, buffer_len);
  mcrypt_generic_deinit (td);
  mcrypt_module_close(td);

  return 0;
}

int decrypt(void* buffer, int buffer_len, char* IV, char* key, int key_len){
  MCRYPT td = mcrypt_module_open("rijndael-128", NULL, "cbc", NULL);
  int blocksize = mcrypt_enc_get_block_size(td);
  if( buffer_len % blocksize != 0 )
    return 1;

  mcrypt_generic_init(td, key, key_len, IV);
  mdecrypt_generic(td, buffer, buffer_len);
  mcrypt_generic_deinit (td);
  mcrypt_module_close(td);

  return 0;
}

void display(char* ciphertext, int len){
  int v;
  for (v=0; v<len; v++){
    if(v % 16 == 0) putchar('\n');
    printf("%02X ", (unsigned char)ciphertext[v]);
  }
  printf("\n");
}

int main()
{
  unsigned char plaintext[256];
  unsigned char IV[16] = {0xFA,0x8D,0x46,0x54,0x83,0xC6,0xED,0xD8,
    0x37,0x5A,0x9D,0xC1,0x3E,0x69,0x1B,0x04};
  unsigned char key[16] = {0x53, 0x75, 0x7a, 0x79, 0x26, 0x52, 0x69, 0x63,
    0x68, 0x42, 0x65, 0x72, 0x67, 0x69, 0x6e, 0x20};
  int keysize = 16; /* 128 bits */
  char* buffer;
  int buffer_len = 256;
  FILE *fp;

  fp = fopen("readbuf.bin", "r");
  fread(plaintext, 1, 256, fp);
  fread(plaintext, 1, 256, fp);
  fclose(fp);

  buffer = calloc(1, buffer_len);
  strncpy(buffer, plaintext, buffer_len);

  //printf("plain:   %s\n", plaintext);
  encrypt(buffer, buffer_len, IV, key, keysize); 
  printf("cipher:  "); display(buffer , buffer_len);
  //decrypt(buffer, buffer_len, IV, key, keysize);
  //printf("decrypt: %s\n", buffer);

  return 0;
}

I need to encrypt byte 255~511 of readbuf.bin I get the result byte 0 ~ 0x6F is correct, but since byte 0x70 the result is incorrect Is there mistake in the source code?


Solution

  • Thanks everyone who take care this question, I found the root cause through review source code again and again...

    the root cause is the function call:

    strncpy(buffer, plaintext, buffer_len);
    

    Everything going well, while I replace strncpy() with memcpy()

    memcpy(buffer, plaintext, buffer_len);
    

    Also, I follow WhozCraig suggestion modifying the source code as below:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <mcrypt.h>
    #include <math.h>
    #include <stdint.h>
    
    int encrypt(void* buffer, int buffer_len, char* IV, char* key, int key_len)
    {
      MCRYPT td = mcrypt_module_open("rijndael-128", NULL, "cbc", NULL);
      int blocksize = mcrypt_enc_get_block_size(td);
      int n_blocks = buffer_len / blocksize;
      if( buffer_len % blocksize != 0 )
        return 1;
    
      mcrypt_generic_init(td, key, key_len, IV);
      for (int i = 0; i < n_blocks; i++) 
        mcrypt_generic(td, ((unsigned char* )buffer) + (i * blocksize), blocksize);
      mcrypt_generic_deinit (td);
      mcrypt_module_close(td);
    
      return 0;
    }
    
    int decrypt(void* buffer, int buffer_len, char* IV, char* key, int key_len){
      MCRYPT td = mcrypt_module_open("rijndael-128", NULL, "cbc", NULL);
      int blocksize = mcrypt_enc_get_block_size(td);
      int n_blocks = buffer_len / blocksize;
      if( buffer_len % blocksize != 0 )
        return 1;
    
      mcrypt_generic_init(td, key, key_len, IV);
      for (int i = 0; i < n_blocks; i++) 
        mdecrypt_generic(td, ((unsigned char *)buffer) + (i * blocksize), blocksize);
      mcrypt_generic_deinit (td);
      mcrypt_module_close(td);
    
      return 0;
    }
    
    void display(char* ciphertext, int len){
      int v;
      for (v=0; v<len; v++){
        if(v % 16 == 0) putchar('\n');
        printf("%02X ", (unsigned char)ciphertext[v]);
      }
      printf("\n");
    }
    
    int main()
    {
      unsigned char plaintext[256];
      unsigned char IV[16] = {0xFA,0x8D,0x46,0x54,0x83,0xC6,0xED,0xD8,
        0x37,0x5A,0x9D,0xC1,0x3E,0x69,0x1B,0x04};
      unsigned char key[16] = {0x53, 0x75, 0x7a, 0x79, 0x26, 0x52, 0x69, 0x63,
        0x68, 0x42, 0x65, 0x72, 0x67, 0x69, 0x6e, 0x20};
      int keysize = 16; /* 128 bits */
      char* buffer;
      int buffer_len = 256;
      FILE *fp;
    
      fp = fopen("readbuf.bin", "r");
      fread(plaintext, 1, 256, fp);
      fread(plaintext, 1, 256, fp);
      fclose(fp);
    
      buffer = calloc(1, buffer_len);
      //strncpy(buffer, plaintext, buffer_len);
      memcpy(buffer, plaintext, buffer_len);
    
      printf("plain:   %s\n", plaintext);
      encrypt(buffer, buffer_len, IV, key, keysize); 
      printf("cipher:  "); display(buffer , buffer_len);
      decrypt(buffer, buffer_len, IV, key, keysize);
      printf("decrypt: %s\n", buffer);
    
      return 0;
    }