vico
vico

Reputation: 18201

OpenSSL AES_cfb128_encrypt public/private key C++

I have very basic encrypt/decrypt application that uses constant key. How to make this application to work with public/private key? Is it enough to generate keys with openssl and use them in my code variable ckey?

Can I somehow generate keys with my library?

#include "stdafx.h"
#include <openssl/aes.h>
#include <algorithm>
#include <iostream>


int _tmain(int argc, _TCHAR* argv[])
{
    int bytes_read, bytes_written;
    unsigned char indata[AES_BLOCK_SIZE + 1];
    unsigned char outdata[AES_BLOCK_SIZE + 1];
    std::fill(indata, indata + AES_BLOCK_SIZE, 0);
    std::fill(outdata, outdata + AES_BLOCK_SIZE, 0);


    /* ckey and ivec are the two 128-bits keys necesary to
     en- and recrypt your data.  Note that ckey can be
     192 or 256 bits as well */
    unsigned char ckey[] = "thiskeyisverybad";
    const char ivecstr[AES_BLOCK_SIZE] = "goodbyworldkey\0";
    unsigned char ivec[] = "dontusethisinput";

    /* data structure that contains the key itself */
    AES_KEY key;

    /* set the encryption key */
    AES_set_encrypt_key(ckey, 128, &key);

    /* set where on the 128 bit encrypted block to begin encryption*/
    int num = 0;


    FILE* ifp;
    FILE* oefp;
    FILE* odfp;

    ifp = fopen("infile.txt", "r");
    if (ifp == NULL) perror("Error opening file");

    oefp = fopen("outEncryptfile.txt", "w");
    if (oefp == NULL) perror("Error opening file");

    odfp = fopen("outDecryptfile.txt", "w");
    if (odfp == NULL) perror("Error opening file");

    int b = 0;
    int w = 0;

    memcpy(ivec, ivecstr, AES_BLOCK_SIZE);
    while (1)
    {
        std::fill(indata, indata + AES_BLOCK_SIZE, 0);

        bytes_read = fread(indata, 1, AES_BLOCK_SIZE, ifp);
        b = b + bytes_read;
        indata[AES_BLOCK_SIZE] = 0;
        //std::cout << "original data:\t" << indata << std::endl;
        std::cout << indata;

        AES_cfb128_encrypt(indata, outdata, bytes_read, &key, ivec, &num,AES_ENCRYPT);



        bytes_written = fwrite(outdata, 1, bytes_read, oefp);
        w = w + bytes_written;

        if (bytes_read < AES_BLOCK_SIZE)
            break;
    }

    fclose(oefp);

    oefp = fopen("outEncryptfile.txt", "r");
    if (oefp == NULL) perror("Error opening file");

    b = 0;
    memcpy(ivec, ivecstr, AES_BLOCK_SIZE);
    while (1)
    {
        bytes_read = fread(indata, 1, AES_BLOCK_SIZE, oefp);
        b = b + bytes_read;
        indata[AES_BLOCK_SIZE] = 0;
        std::cout << "original data:\t" << indata << std::endl;
        AES_cfb128_encrypt(indata, outdata, bytes_read, &key, ivec, &num, AES_DECRYPT);
        std::cout << "decrypted data:\t" << outdata << std::endl;
        bytes_written = fwrite(outdata, 1, bytes_read, odfp);
        if (bytes_read < AES_BLOCK_SIZE)
            break;
    }
    fclose(odfp);

    return 0;
}

Upvotes: 1

Views: 2571

Answers (1)

jww
jww

Reputation: 102346

I have very basic encrypt/decrypt application that uses constant key. How to make this application to work with public/private key? Is it enough to generate keys with openssl and use them in my code variable ckey?

You can't. Shared key and private key cryptography are sufficiently different to ensure you cannot do it. Or maybe more correctly, you can't do it without a major redesign and rewrite.

OpenSSL provides two (maybe three) high level primitives of interest for your issue. Here's the documentation on them:

  1. EVP Symmetric Encryption and Decryption
  2. EVP Asymmetric Encryption and Decryption

The "maybe three" is:

  1. EVP Authenticated Encryption and Decryption

Here are the common API calls when using (1) EVP Symmetric Encryption and (2) EVP Asymmetric Encryption from above:

EVP Symmetric Encryption

  • EVP_CIPHER_CTX_new
  • EVP_EncryptInit_ex
  • EVP_EncryptUpdate
  • EVP_EncryptFinal_ex

EVP Asymmetric Encryption

  • EVP_CIPHER_CTX_new
  • EVP_SealInit
  • EVP_SealUpdate
  • EVP_SealFinal
  • EVP_CIPHER_CTX_free

With all that said, its not really a design problem in OpenSSL. The APIs are well defined for operation at hand - symmetric encryption, authenticated encryption, asymmetric encryption, signing, verifying, hashing, mac'ing, etc. It would be difficult to shoehorn everything into one set of API calls.

The code you provided, using AES_KEY, AES_set_encrypt_key, and friends, is even harder to work with. Its a specialized software-only AES implementation that you get if you configure with no-asm. It also has some landmines, like being non-portable in some cases. For example, I seem to recall special care has to be taken on some big-endian platforms because you need to byte-swap the key.


Yu might also want to look at how IPsec and TLS do things. They break workflows up into two parts: (1) key exchange (or key transport) and (2) bulk encryption. The key exchange portion happens using public/private key cryptography. and establishes a shared secret. Once the shared secret is established, symmetric ciphers are keyed and bulk encryption takes place.

IPsec has a more defensive security posture. TLS runs a bit fast and loose for my taste. I only use TLS when requirements tell me to do so (like interop'ing with existing systems). Otherwise, I prefer in-app VPNs or IPsec-like schemes.

Upvotes: 1

Related Questions