Not able to decrypt the entire file using EVP_aes_256_gcm() and fwrite

  aes-gcm, c++, openssl, openssl-engine

I am first encrypting the following file (example.txt)

    Students who start their homework early tend to do well.
    Those who don't... well...
    Have you started thinking about projects?
    Students who start their homework early tend to do well.
    Those who don't... well...
    Have you started thinking about projects?
    Students who start their homework early tend to do well.
    Those who don't... well...
    Have you started thinking about projects?
    Students who start their homework early tend to do well.
    Those who don't... well...
    Have you started thinking about projects?
    Students who start their homework early tend to do well.
    Those who don't... well...
    Have you started thinking about projects?
    Students who start their homework early tend to do well.
    Those who don't... well...
    Have you started thinking about projects?
    Students who start their homework early tend to do well.
    Those who don't... well...
    Have you started thinking about projects?
    Students who start their homework early tend to do well.
    Those who don't... well...
    Have you started thinking about projects?
    Students who start their homework early tend to do well.
    Those who don't... well...
    Have you started thinking about projects?
    Time to start :)

using the code:

    #include <openssl/conf.h>
    #include <openssl/evp.h>
    #include <openssl/err.h>
    #include <string.h>
    #include <openssl/aes.h>
    #include <openssl/rand.h>
    void handleErrors(void)
    {
        ERR_print_errors_fp(stderr);
        abort();
    }

    int encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *aad,
        int aad_len, unsigned char *key, unsigned char *iv,
        unsigned char *ciphertext, unsigned char *tag)
    {
        EVP_CIPHER_CTX *ctx;

        int len=0, ciphertext_len=0;
        if(!(ctx = EVP_CIPHER_CTX_new()))
            handleErrors();
        if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL))
            handleErrors();

        if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 16, NULL))
            handleErrors();

        if(1 != EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv)) handleErrors();

        if(1 != EVP_EncryptUpdate(ctx, NULL, &len, aad, aad_len))
            handleErrors();

         while(ciphertext_len<=plaintext_len-16)
         {
    if(1 != EVP_EncryptUpdate(ctx, ciphertext+ciphertext_len,&len,plaintext+ciphertext_len, 16))
            handleErrors();
    ciphertext_len+=len;
         }
         if(1 != EVP_EncryptUpdate(ctx, ciphertext+ciphertext_len, &len, 
     plaintext+ciphertext_len, plaintext_len-ciphertext_len))
             handleErrors();
         ciphertext_len+=len;
    if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + ciphertext_len, &len))
    handleErrors();
        ciphertext_len += len;

        if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag))
            handleErrors();

        EVP_CIPHER_CTX_free(ctx);

        return ciphertext_len;
    }
    int main (int argc, char* argv [])
    {


        /* A 256 bit key */
        unsigned char buffer[2048];
        FILE *in_file  = fopen(argv[1], "rb+");

        FILE *out_file  = fopen(strcat(argv[1],".ufsec"), "wb+");
        fread(buffer, 1, 2048, in_file);
        // unsigned char *key ;

        /* A 128 bit IV */
        unsigned char iv[16]="abcdefghijklmnop";
        unsigned char aad[16]="abcdefghijklmnop";

        /* Message to be encrypted */
        unsigned char *plaintext = buffer;
        unsigned char* salt = (unsigned char*) "CalciumChloride";
        unsigned char ciphertext[1024+2048];
        unsigned char tag[]="abcde";
        unsigned char password[32];
        printf("nEnter password:");
        scanf("%s",password);
        unsigned char *key = password;

           if(!PKCS5_PBKDF2_HMAC(((const char*)key), strlen((char*)key),salt,strlen((const char*)(salt)),4096,EVP_sha512(),32,key))
            {
                printf("Error in key generationn");
                exit(1);
            }
           printf("nKey is: ");
           for(int i=0;i<32;i++)
           {
               printf("%02x", key[i]);
           }
            /* Buffer for the decrypted text */
            unsigned char decryptedtext[2048+EVP_MAX_BLOCK_LENGTH];

            int decryptedtext_len, ciphertext_len;



        }

and getting the output cipher in a file (example.txt.ufsec) and i am getting this output on terminal

but when i am trying to decrypt this example.txt.ufsec using the following code:

    #include <openssl/conf.h>
    #include <openssl/evp.h>
    #include <openssl/err.h>
    #include <string.h>
    #include <openssl/aes.h>
    #include <openssl/rand.h>
    void handleErrors(void)
    {
        ERR_print_errors_fp(stderr);
        abort();
    }
    int decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *aad, int aad_len, unsigned char *tag, unsigned char *key, unsigned char *iv, unsigned char *plaintext)
    {
        EVP_CIPHER_CTX *ctx;
        int len=0, plaintext_len=0, ret;

        /* Create and initialise the context */
            if(!(ctx = EVP_CIPHER_CTX_new())) 
            handleErrors();

        /* Initialise the decryption operation. */
        if(!EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL))
            handleErrors();

        /* Set IV length. Not necessary if this is 12 bytes (96 bits) */
        if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 16, NULL))
            handleErrors();

        /* Initialise key and IV */
        if(!EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv)) 
            handleErrors();

        /* Provide any AAD data. This can be called zero or more times as
         * required
         */
        if(!EVP_DecryptUpdate(ctx, NULL, &len, aad, aad_len))
            handleErrors();

        /* Provide the message to be decrypted, and obtain the plaintext output.
         * EVP_DecryptUpdate can be called multiple times if necessary
         */
         while(plaintext_len<=ciphertext_len-16)
         {
            if(1!=EVP_DecryptUpdate(ctx, plaintext+plaintext_len, &len, ciphertext+plaintext_len, 16))
                handleErrors();
            plaintext_len+=len;
         }
         if(1!=EVP_DecryptUpdate(ctx, plaintext+plaintext_len, &len, ciphertext+plaintext_len, ciphertext_len-plaintext_len))
                handleErrors();
         plaintext_len+=len;

        /* Set expected tag value. Works in OpenSSL 1.0.1d and later */
        if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, tag))
            handleErrors();

        /* Finalise the decryption. A positive return value indicates success,
         * anything else is a failure - the plaintext is not trustworthy.
         */
        ret = EVP_DecryptFinal_ex(ctx, plaintext + plaintext_len, &len);

        /* Clean up */
        EVP_CIPHER_CTX_free(ctx);

        if(ret > 0)
        {
            /* Success */
            plaintext_len += len;
            return plaintext_len;
        }
        else
        {
            /* Verify failed */
            return -1;
        }
    }
    int main (int argc, char* argv [])
    {
        /*
         * Set up the key and iv. Do I need to say to not hard code these in a
         * real application? :-)
         */

        /* A 256 bit key */
        unsigned char buffer[6000];
        FILE *in_file  = fopen(argv[1], "rb+");

        FILE *out_file  = fopen(strtok(argv[1],"."), "wb+");
        fread(buffer, sizeof(buffer), 1, in_file);
        // unsigned char *key ;
        printf("%s",buffer);
        /* A 128 bit IV */
        unsigned char iv[16]="abcdefghijklmnop";
        unsigned char aad[16]="abcdefghijklmnop";

        decryptedtext_len = decrypt(ciphertext, strlen((char *)ciphertext), aad, sizeof(aad),tag, key, iv, decryptedtext);

        /* Add a NULL terminator. We are expecting printable text */
        decryptedtext[decryptedtext_len] = '{$content}';

        /* Show the decrypted text */
        printf("Decrypted text is:n");
        printf("%sn", decryptedtext);
        fwrite(decryptedtext, decryptedtext_len, 1, out_file);
        fclose(in_file);
        fclose(out_file);
        return 0;
    }

i am getting this as terminal output instead of the whole example.txt.
This is what the output looks like in the decrypted file "example" (again, not getting decrypted fully.)

What am I doing incorrectly here?

Source: Windows Questions C++

LEAVE A COMMENT