AES CTR encryption and decryption


Wajahat

So I have this code that basically encrypts two plain text messages and then tries to decrypt them and print them. The problem is that the first message recovers just fine, but the second is garbage. I downloaded this code from this tutorial and modified it to work with strings instead of files as I need it to send encrypted text over a socket. So other endpoints won't know the length of the plaintext, is it possible to find that length, or must the length of the plaintext be sent with the password somehow?

Now, I think there is a problem with the break condition for decryption.

Also, is the main() code conceptually correct: encrypt the message with the updated state, then reset the state and decrypt the message with the updated state?

Is there a way to find out the actual length of the ciphertext (not the buffer)?

This is just my dummy program trying to understand how AES CTR works.

#include <openssl/aes.h>
#include <openssl/rand.h> 
#include <openssl/hmac.h>
#include <openssl/buffer.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>

// Code example uses partail code from: http://stackoverflow.com/questions/3141860/aes-ctr-256-encryption-mode-of-operation-on-openssl
// Mostly in the ctr_ state, and init_ctr functions. 

struct ctr_state 
{ 
    unsigned char ivec[AES_BLOCK_SIZE];  
    unsigned int num; 
    unsigned char ecount[AES_BLOCK_SIZE]; 
}; 

int init_ctr(struct ctr_state *state, const unsigned char iv[16])
{        
    /* aes_ctr128_encrypt requires 'num' and 'ecount' set to zero on the
     * first call. */
    state->num = 0;
    memset(state->ecount, 0, AES_BLOCK_SIZE);

    /* Initialise counter in 'ivec' to 0 */
    memset(state->ivec + 8, 0, 8);

    /* Copy IV into 'ivec' */
    memcpy(state->ivec, iv, 8);
}

void fencrypt(char* text, char* cipher, const unsigned char* enc_key, struct ctr_state* state)
{ 
    AES_KEY key;
    unsigned char indata[AES_BLOCK_SIZE]; 
    unsigned char outdata[AES_BLOCK_SIZE];
    int offset=0;
    //Initializing the encryption KEY
    if (AES_set_encrypt_key(enc_key, 128, &key) < 0)
    {
        fprintf(stderr, "Could not set encryption key.");
        exit(1); 
    }

    //Encrypting Blocks of 16 bytes and writing the output.txt with ciphertext  
    while(1)    
    {
        printf("while going\n");
        memcpy(indata, text+offset, AES_BLOCK_SIZE); 
        AES_ctr128_encrypt(indata, outdata, AES_BLOCK_SIZE, &key, state->ivec, state->ecount, &state->num);

        memcpy(cipher+offset, outdata, AES_BLOCK_SIZE);
        offset=offset+AES_BLOCK_SIZE;
        if (offset > strlen(text))
        {
            break;
        }
    }
}

void fdecrypt(char* cipher, char* text, const unsigned char* enc_key, struct ctr_state* state)
{   
    AES_KEY key;
    unsigned char indata[AES_BLOCK_SIZE]; 
    unsigned char outdata[AES_BLOCK_SIZE];
    int offset=0;
    //Initializing the encryption KEY
    if (AES_set_encrypt_key(enc_key, 128, &key) < 0)
    {
        fprintf(stderr, "Could not set decryption key.");
        exit(1);
    }

    //Encrypting Blocks of 16 bytes and writing the output.txt with ciphertext       
    while(1)    
    {
        memcpy(indata, cipher+offset, AES_BLOCK_SIZE);  
        //printf("%i\n", state.num);
        AES_ctr128_encrypt(indata, outdata, AES_BLOCK_SIZE, &key, state->ivec, state->ecount, &state->num);

        memcpy(text+offset, outdata, AES_BLOCK_SIZE); 
        offset=offset+AES_BLOCK_SIZE;
        if (offset > strlen(cipher))
        {
            break;
        }
    }
}

int main(int argc, char *argv[])
{
    unsigned char iv[AES_BLOCK_SIZE];
    struct ctr_state state;
    char* plain="quick brown fox jumped over the lazy dog what ";
    char* plain2="a dog he is idiot who is the genius ";
    char cipher[128];
    char cipher2[128];
    char recovered[128];
    char recovered2[128];
    const unsigned char* enc_key="123456789abcdef0";

    if(!RAND_bytes(iv, AES_BLOCK_SIZE))
    {
        fprintf(stderr, "Could not create random bytes.");
        exit(1);    
    }
    init_ctr(&state, iv); //Counter call
    printf("Plain text length:%lu\n",strlen(plain));
    // BIO_dump_fp(stdout, plain, strlen(plain));
    // printf("Plain text:%s\n",plain);
    fencrypt(plain, cipher,enc_key,&state);
    fencrypt(plain2, cipher2,enc_key,&state);
    // cipher[strlen(plain)]='\0';
    // BIO_dump_fp(stdout, cipher, strlen(plain));
    init_ctr(&state, iv); //Counter call
    fdecrypt(cipher,recovered,enc_key,&state);
    fdecrypt(cipher2,recovered2,enc_key,&state);
    // printf("Cipher text length:%lu\n",strlen(cipher));
    printf("Recovered text:%s\n",recovered);
    printf("Recovered text:%s\n",recovered2);
    return 0;
}
Barmac Semilani

CTR mode does not require separate encryption and decryption methods. The encryption key can only be set once. OpenSSL AES_ctr128_encrypttakes care of most of the work, so the code can be simplified.

Also, we do need vector tests. Here we are just testing with random text "quick brown fox...", returning the same text, but there is no guarantee that "cipher" is correct and whether the encryption is AES quality or not. I'll add a quick vector test later if I have time.

void init_ctr(struct ctr_state *state, const unsigned char iv[16])
{        
    state->num = 0;
    memset(state->ecount, 0, 16);
    memcpy(state->ivec, iv, 16);
}

void crypt_message(const u8* src, u8* dst, unsigned int src_len, const AES_KEY* key, const u8* iv)
{   
   struct ctr_state state;
   init_ctr(&state, iv);
   AES_ctr128_encrypt(src, dst, src_len, key, state.ivec, state.ecount, &state.num);
}

int main()
{
   int len;
   char source[128];
   char cipher[128];
   char recovered[128];
   unsigned char iv[AES_BLOCK_SIZE];

   const unsigned char* enc_key = (const unsigned char*)"123456789abcdef0";

   if(!RAND_bytes(iv, AES_BLOCK_SIZE)) 
   {
       fprintf(stderr, "Could not create random bytes.");
       exit(1);    
   }

   AES_KEY key;
   AES_set_encrypt_key(enc_key, 128, &key);

   strcpy(source, "quick brown fox jumped over the lazy dog what.");
   len = strlen(source);
   memset(recovered, 0, sizeof(recovered));
   crypt_message((const u8*)source, (u8*)cipher, len, &key, iv);
   crypt_message((const u8*)cipher, (u8*)recovered, len, &key, iv);
   printf("Recovered text:%s\n", recovered);

   strcpy(source, "a dog he is idiot who is the genius.");
   len = strlen(source);
   memset(recovered, 0, sizeof(recovered));
   crypt_message((const u8*)source, (u8*)cipher, len, &key, iv);
   crypt_message((const u8*)cipher, (u8*)recovered, len, &key, iv);
   printf("Recovered text:%s\n", recovered);

   return 0;
}

To encrypt/decrypt files, or send/receive:

void crypt_file(const u8* src_file, const u8* dst_file, const AES_KEY* key, const u8* iv)
{   
   struct ctr_state state;
   init_ctr(&state, iv);

   const int buffer_size = 512; //not less than 16
   unsigned char buffer_in[buffer_size];
   unsigned char buffer_out[buffer_size];
   int bytes_read;

   //open files and/or socket
   //file/message loop
   {
      //read source, obtain buffer_in and bytes_read
      AES_ctr128_encrypt(buffer_in, buffer_out, bytes_read, key, state.ivec, state.ecount, &state.num);
      //write buffer_out/bytes_read to destination
   }
   //close handles
}

In your code, fdecrypt()include strlen(cipher). However cipher, strlen cannot be used with pure binary data. You must provide the length manually. I add lenparameters to fdecrypt. Simple in mainmy use strlen(plaintext), but it should be real length cipherdata. Changes are represented by ##change

void fdecrypt(unsigned int len, char* cipher, char* text, const unsigned char* enc_key, struct ctr_state* state)
{   
    AES_KEY key;
    unsigned char indata[AES_BLOCK_SIZE]; 
    unsigned char outdata[AES_BLOCK_SIZE];
    int offset=0;
    //Initializing the encryption KEY
    if (AES_set_encrypt_key(enc_key, 128, &key) < 0)
    {
        fprintf(stderr, "Could not set decryption key.");
        exit(1);
    }

    //Encrypting Blocks of 16 bytes and writing the output.txt with ciphertext       
    while(1)    
    {
        memcpy(indata, cipher+offset, AES_BLOCK_SIZE);  
        //printf("%i\n", state.num);
        AES_ctr128_encrypt(indata, outdata, AES_BLOCK_SIZE, &key, state->ivec, state->ecount, &state->num);

        memcpy(text+offset, outdata, AES_BLOCK_SIZE); 
        offset=offset+AES_BLOCK_SIZE;
        //if (offset > strlen(cipher))##changed
        if (offset > len)
        {
            break;
        }
    }
}

int main(int argc, char *argv[])
{
    unsigned char iv[AES_BLOCK_SIZE];
    struct ctr_state state;
    char* plain="quick brown fox jumped over the lazy dog what ";
    char* plain2="a dog he is idiot who is the genius ";
    char cipher[128];
    char cipher2[128];
    char recovered[128];
    char recovered2[128];
    const unsigned char* enc_key=(const unsigned char*)"123456789abcdef0";

    if(!RAND_bytes(iv, AES_BLOCK_SIZE))
    {
        fprintf(stderr, "Could not create random bytes.");
        exit(1);    
    }

    init_ctr(&state, iv); //Counter call
    printf("Plain text length:%lu\n",strlen(plain));
    // BIO_dump_fp(stdout, plain, strlen(plain));
    // printf("Plain text:%s\n",plain);
    fencrypt(plain, cipher,enc_key,&state);
    fencrypt(plain2, cipher2,enc_key,&state);
    // cipher[strlen(plain)]='\0';
    // BIO_dump_fp(stdout, cipher, strlen(plain));
    init_ctr(&state, iv); //Counter call
    fdecrypt(strlen(plain), cipher,recovered,enc_key,&state);//##changed
    fdecrypt(strlen(plain2), cipher2,recovered2,enc_key,&state);//##changed
    // printf("Cipher text length:%lu\n",strlen(cipher));
    printf("Recovered text:%s\n",recovered);
    printf("Recovered text:%s\n",recovered2);
    return 0;
}

Related


AES CTR encryption and decryption

Wajahat So I have this code that basically encrypts two plain text messages and then tries to decrypt them and print them. The problem is that the first message recovers just fine, but the second is garbage. I downloaded this code from this tutorial and modifi

AES CTR encryption and decryption

Wajahat So I have this code that basically encrypts two plain text messages and then tries to decrypt them and print them. The problem is that the first message recovers just fine, but the second is garbage. I downloaded this code from this tutorial and modifi

AES CTR encryption and decryption

Wajahat So I have this code that basically encrypts two plain text messages and then tries to decrypt them and print them. The problem is that the first message recovers just fine, but the second is garbage. I downloaded this code from this tutorial and modifi

AES CTR encryption and decryption

Wajahat So I have this code that basically encrypts two plain text messages and then tries to decrypt them and print them. The problem is that the first message recovers just fine, but the second is garbage. I downloaded this code from this tutorial and modifi

AES CTR encryption and decryption

Wajahat So I have this code that basically encrypts two plain text messages and then tries to decrypt them and print them. The problem is that the first message recovers just fine, but the second is garbage. I downloaded this code from this tutorial and modifi

AES-CTR encryption in Go and decryption in CryptoJS

Mark: I'm having trouble decrypting text encrypted in Go lang using CryptoJS. Here is the Go code : https://play.golang.org/p/xCbl48T_iN package main import ( "crypto/aes" "crypto/cipher" "encoding/base64" "fmt" ) func main() { key := []b

AES-CTR encryption in Go and decryption in CryptoJS

Mark: I'm having trouble decrypting text encrypted in Go lang using CryptoJS. Here is the Go code : https://play.golang.org/p/xCbl48T_iN package main import ( "crypto/aes" "crypto/cipher" "encoding/base64" "fmt" ) func main() { key := []b

AES-CTR encryption in Go and decryption in CryptoJS

Mark: I'm having trouble decrypting text encrypted in Go lang using CryptoJS. Here is the Go code : https://play.golang.org/p/xCbl48T_iN package main import ( "crypto/aes" "crypto/cipher" "encoding/base64" "fmt" ) func main() { key := []b

AES-CTR encryption in Go and decryption in CryptoJS

Mark: I'm having trouble decrypting text encrypted in Go lang using CryptoJS. Here is the Go code : https://play.golang.org/p/xCbl48T_iN package main import ( "crypto/aes" "crypto/cipher" "encoding/base64" "fmt" ) func main() { key := []b

AES-CTR encryption in Go and decryption in CryptoJS

Mark: I'm having trouble decrypting text encrypted in Go lang using CryptoJS. Here is the Go code : https://play.golang.org/p/xCbl48T_iN package main import ( "crypto/aes" "crypto/cipher" "encoding/base64" "fmt" ) func main() { key := []b

AES-CTR encryption in Go and decryption in CryptoJS

Mark: I'm having trouble decrypting text encrypted in Go lang using CryptoJS. Here is the Go code : https://play.golang.org/p/xCbl48T_iN package main import ( "crypto/aes" "crypto/cipher" "encoding/base64" "fmt" ) func main() { key := []b

AES 256 CTR encryption/decryption with Visual Studio and Openssl

Tanatos Daniel Hello everyone! I am trying to encrypt and decrypt a string using aes ctr with a 256 bit key. I have posted the code below. I'm missing something, but I don't know what. The Checktext produced by decryption is different from the plaintext. Thank

AES 256 CTR encryption/decryption with Visual Studio and Openssl

Tanatos Daniel Hello, gentlemen! I am trying to encrypt and decrypt a string using aes ctr with a 256 bit key. I have posted the code below. I'm missing something, but I don't know what. The Checktext produced by decryption is different from the plaintext. Tha

AES 256 CTR encryption/decryption with Visual Studio and Openssl

Tanatos Daniel Hello, gentlemen! I am trying to encrypt and decrypt a string using aes ctr with a 256 bit key. I have posted the code below. I'm missing something, but I don't know what. The Checktext produced by decryption is different from the plaintext. Tha

AES encryption and decryption in Java

death: I'm pretty new to encryption/decryption and have to encrypt some data files, but not entirely sure I'm going about it the right way. Right now, I have a script to encrypt all files that are not included in my repository, but the decryptor is included in

AES encryption and decryption

More I quickly wrote an application where I need AES encryption and decryption functionality, I received encrypted data from another .Net solution, but I couldn't find a solution. Here is my .net encryption: public static byte[] AES_Encrypt(byte[] bytesToBeEn

AES encryption and decryption

More I quickly wrote an application where I need AES encryption and decryption functionality, I received encrypted data from another .Net solution, but I couldn't find a solution. Here is my .net encryption: public static byte[] AES_Encrypt(byte[] bytesToBeEn

Java AES encryption and decryption

Praneeth I want to encrypt and decrypt a password using 128 bit AES encryption and a 16 byte key. There was an error javax.crypto.BadPaddingExceptiondecrypting the value . Do I lose anything when decrypting? public static void main(String args[]) { Test t

Java AES encryption and decryption

Praneeth I want to encrypt and decrypt a password using 128 bit AES encryption and a 16 byte key. There was an error javax.crypto.BadPaddingExceptiondecrypting the value . Do I lose anything when decrypting? public static void main(String args[]) { Test t

AES encryption and decryption in Java

death: I'm pretty new to encryption/decryption and have to encrypt some data files, but not entirely sure I'm going about it the right way. Right now, I have a script to encrypt all files that are not included in my repository, but the decryptor is included in

AES encryption and decryption in Java

death: I'm pretty new to encryption/decryption and have to encrypt some data files, but not entirely sure I'm going about it the right way. Right now, I have a script to encrypt all files that are not included in my repository, but the decryptor is included in

AES encryption and decryption

More I quickly wrote an application where I need AES encryption and decryption functionality, I received encrypted data from another .Net solution, but I couldn't find a solution. Here is my .net encryption: public static byte[] AES_Encrypt(byte[] bytesToBeEn

AES 256 encryption and decryption

Link I'm new to AWS, how does AES 256 encryption work in s3 buckets? I have uploaded the file to my s3 bucket and encrypted it with AES 256 encryption, but I am able to download the file easily. ? Should I be decrypted? of Yes, that's working as expected. Once

AES encryption hardware decryption

Money Julian I am using a Nordic Nrf51822 chip which has hardware support for AES encryption but no decryption hardware support, so I came up with the following method sender->XOR(data, AES(XOR(salt, counter=1)) -> Receiver receiver is Being able to XOR the da

Java AES encryption and decryption

Praneeth I want to encrypt and decrypt a password using 128 bit AES encryption and a 16 byte key. There was an error javax.crypto.BadPaddingExceptiondecrypting the value . Do I lose anything when decrypting? public static void main(String args[]) { Test t

AES encryption and decryption in Java

death: I'm pretty new to encryption/decryption and have to encrypt some data files, but not entirely sure I'm going about it the right way. Right now, I have a script to encrypt all files that are not included in my repository, but the decryptor is included in

AES encryption and decryption in Java

death: I'm pretty new to encryption/decryption and have to encrypt some data files, but not entirely sure I'm going about it the right way. Right now, I have a script to encrypt all files that are not included in my repository, but the decryptor is included in

AES encryption and decryption

More I quickly wrote an application where I need AES encryption and decryption functionality, I received encrypted data from another .Net solution, but I couldn't find a solution. Here is my .net encryption: public static byte[] AES_Encrypt(byte[] bytesToBeEn

AES 256 encryption and decryption

Link I'm new to AWS, how does AES 256 encryption work in s3 buckets? I have uploaded the file to my s3 bucket and encrypted it with AES 256 encryption, but I am able to download the file easily. ? Should I be decrypted? of Yes, that's working as expected. Once