rogergl
rogergl

Reputation: 3771

C output differs from openssl output

Given the following openssl example prog

#include <openssl/evp.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 inlen, outlen;
    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 (;;) {
        inlen = fread(inbuf, 1, 1024, in);
        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 argc, char* argv[])
{
    FILE *fpIn;
    FILE *fpOut;

    fpIn = fopen("text-in.txt", "rb");
    fpOut = fopen("text-out.txt", "wb");

    int test = do_crypt(fpIn, fpOut, 1);

    fclose(fpIn);
    fclose(fpOut);

    return 0;

}

I would expect that

openssl aes-128-cbc -in text-in.txt  -K 0123456789abcdeF -iv 1234567887654321

would create the same output. But it doesn't. The C prog can decrypt the files it encrypted. But it can't decrypt the files encrypted with openssl.

Upvotes: 1

Views: 114

Answers (1)

dbush
dbush

Reputation: 223689

The encryption key and IV are not actually text but binary data.

When you do the encryption on the command line, the -K and -iv arguments expect their input in hex.

So the key you're passing in is actually:

\x01\x23\x45\x67\x89\xab\xcd\xef\x00\x00\x00\x00\x00\x00\x00\x00

And the IV is:

\x12\x34\x56\x78\x87\x65\x43\x21\x00\x00\x00\x00\x00\x00\x00\x00

Both have tail padding of 0's because the key that was specified was too short.

In order to match the program's output, you need to pass in the hex codes of the characters you specified. For example, 1 is 30, 2 is 31, a is 61, F is 46, and so forth:

openssl aes-128-cbc -in text-in.txt  -K 30313233343536373839616263646546 -iv 31323334353637383837363534333231

Upvotes: 1

Related Questions