0

As far as I can see the EVP funktions in openssl only accepts unsigned char * as input. An example code would be:

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

    int len;

    int ciphertext_len;


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

    /* Initialise the encryption operation. */
    if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL))
        handleErrors();

    /*
     * Set IV length if default 12 bytes (96 bits) is not appropriate
     */
    if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, iv_len, NULL))
        handleErrors();

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

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

    /*
     * Provide the message to be encrypted, and obtain the encrypted output.
     * EVP_EncryptUpdate can be called multiple times if necessary
     */
    if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len))
        handleErrors();
    ciphertext_len = len;

    /*
     * Finalise the encryption. Normally ciphertext bytes may be written at
     * this stage, but this does not occur in GCM mode
     */
    if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len))
        handleErrors();
    ciphertext_len += len;

    /* Get the tag */
    if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag))
        handleErrors();

    /* Clean up */
    EVP_CIPHER_CTX_free(ctx);

    return ciphertext_len;
}

I want to open/read any kind of file and use it as plaintext to encrypt it. How would a code look like that would enable me to read any kind of file?

When trying, I allways end up with initialization errors:

    FILE * pFile;
    long lSize;
    char * buffer;  // same error when using: unsigned char * buffer;
    size_t result;

    pFile = fopen ( "test.txt" , "rb" );
    if (pFile==NULL) {fputs ("File error",stderr); exit (1);}

    // obtain file size:
    fseek (pFile , 0 , SEEK_END);
    lSize = ftell (pFile);
    rewind (pFile);

    // allocate memory to contain the whole file:
    buffer = (char*) malloc (sizeof(char)*lSize);
    if (buffer == NULL) {fputs ("Memory error",stderr); exit (2);}

    // copy the file into the buffer:
    result = fread (buffer,1,lSize,pFile);
    if (result != lSize) {fputs ("Reading error",stderr); exit (3);}
    
    cout << typeid(buffer).name() << endl;
    
    
    unsigned char plaintext[] = buffer;   <- Array initializer must be an initializer list or string literal

Is there maybe an other library also supporitng aead or openssl funktion that is more sufficient to do this task?

The error message i get is:

evp-encrypt_input_file.cpp:43:16: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
     if (result != lSize) {fputs ("Reading error",stderr); exit (3);}
         ~~~~~~~^~~~~~~~
evp-encrypt_input_file.cpp:48:19: error: initializer fails to determine size of ‘plaintext’
     unsigned char plaintext[] = buffer;
                   ^~~~~~~~~
evp-encrypt_input_file.cpp:48:33: error: array must be initialized with a brace-enclosed initializer
     unsigned char plaintext[] = buffer;

Also the code has to be in c++, can not use c.

root
  • 35
  • 5

1 Answers1

0

Found a more efficient way to solve the problem. Using unsigned char * was a bad idea in the fist place. In the official documentation there is a way beffer solution. However I have made two cahnges.

First cahnge:

EVP_CipherInit_ex(&ctx, EVP_aes_128_cbc(), NULL, NULL, NULL,do_encrypt); to EVP_CipherInit_ex(ctx, EVP_aes_128_cbc(), NULL, NULL, NULL,do_encrypt);

Second change:

inlen = fread(inbuf, 1, 1024, in); to size_t a = fread(inbuf, 1, 1024, in); inlen = int(a);

The code is as follows:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/aes.h>
#include <openssl/rand.h>

int do_crypt(FILE *in, FILE *out, int do_encrypt){
    /* Allow enough space in output buffer for additional block */
    unsigned char inbuf[1024], outbuf[1024 + EVP_MAX_BLOCK_LENGTH];
    int outlen;
    int inlen;
    EVP_CIPHER_CTX *ctx;
    /* Bogus key and IV: we'd normally set these from
     * another source.
     */
    unsigned char key[] = "0123456789abcdeF";
    unsigned char iv[] = "1234567887654321";

    /* Don't set key or IV right away; we want to check lengths */
    ctx = EVP_CIPHER_CTX_new();
    EVP_CipherInit_ex(ctx, EVP_aes_128_cbc(), NULL, NULL, NULL, do_encrypt);
    OPENSSL_assert(EVP_CIPHER_CTX_key_length(ctx) == 16);
    OPENSSL_assert(EVP_CIPHER_CTX_iv_length(ctx) == 16);

    /* Now we can set key and IV */
    EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, do_encrypt);

    for(;;){
        size_t a = fread(inbuf, 1, 1024, in);
        inlen = int(a);
        
        if (inlen <= 0) break;
        if(!EVP_CipherUpdate(ctx, outbuf, &outlen, inbuf, inlen)){
                /* Error */
                EVP_CIPHER_CTX_free(ctx);
                return 0;
                }
        fwrite(outbuf, 1, outlen, out);
        }
    if(!EVP_CipherFinal_ex(ctx, outbuf, &outlen)){
        /* Error */
        EVP_CIPHER_CTX_free(ctx);
        return 0;
        }
    fwrite(outbuf, 1, outlen, out);

    EVP_CIPHER_CTX_free(ctx);
    return 1;
    }

int main(int arg, char* argv[]){
    
    FILE * in = fopen("in_file", "rb");
    FILE * out = fopen("out_file", "wb");
    do_crypt(in, out, 1);
}

root
  • 35
  • 5