C++ class that interfaces to OpenSSL ciphers

I have developed a class named Cipher that allows you to encrypt and decrypt files or strings using the OpenSSL AES-256-CBC cipher and SHA1 digest algorithms. It is interoperable with the openssl command line tool which makes it a good introduction to using OpenSSL for ciphers.

I am re-releasing version 1.2 into the public domain on 2013-11-21 because I wish that I had found something like it when I was starting out with OpenSSL.

Release   Date Description
1.2 2013-11-21 Fixed the problem reported by Mihai Todor at line 300 in cipher.cc.
1.1 2012-09-22 Fixed a valgrind problem at line 298 in cipher.cc as reported by an anonymous user.
1.0 2012-02-14 Initial release with source links corrected as reported by nvanwyen.

1 Downloads

You can download the source code in the following formats:

File Size Check Sum Uncompress Command
cipher-1.2.tar.bz2 15K 17148 tar jxf cipher-1.2.tar.bz2
cipher-1.2.tar.gz 16K 29380 tar zxf cipher-1.2.tar.gz
cipher-1.2.zip 19K 1134 unzip cipher-1.2.zip

2 Build and Test

To build and test the project type make. You must have the openssl headers installed.

  1. On CentOS you can install the openssl headers by running “yum install openssl-devel“.
  2. On cygwin you must download the openssl development package.
  3. On Ubuntu you can install it by running “apt-get install openssl libssl-dev“.

It uses the g++ compiler and has been tested on CentOS 5.5, CentOS 6.4, Ubuntu 11.04, cygwin and Mac OS X 10.9.

2.1 Source Files

Here is the list of source files.

File Description
a.h Doxygen main-page.
cipher.cc Class implementation.
cipher.h Class interface.
ct.cc Tool that allows you to use the class.
doxygen.cfg Doxygen configuration file.
Makefile Makefile.
test.cc Tester.

3 ct

Once it is built there will be a tool called ct.exe. It uses the Cipher class to allow you to encrypt and decrypt files and strings. Type ./ct.exe -h to get information about how to use the tool.

3.1 Example

The following example shows how to use the ct program.

3.2 Help

Here is the program help.

Enjoy!

12 thoughts on “C++ class that interfaces to OpenSSL ciphers”

  1. Hi,
    Thanx for sharing this.

    I’m trying to use your ct.exe (and also your cipher class) to decrypt files that have been encrypted with the commandline version of openssl.

    Encryption:
    openssl aes-256-cbc -a -salt -in file.txt -out file.enc -pass pass:opensesamy
    Decryption:
    ct.exe -d -i file.enc -p opensesamy -o file2.txt

    I’m getting
    “ERROR: EVP_DecryptFinal_ex() failed”

    Do you know if this is due to miss-matching passwords? And if so how to supply the password when encrypting the file with openssl?

  2. thanks for this, 2 questions. here is a very simple example using your code

    #include
    #include
    #include
    #include
    #include
    #include “cipher.h”

    void testDecrypt()
    {
    std::string in = “A9ZeZTZfb0nmrXlCOtf5rw==\n”;
    std::string salt = “”;

    Cipher mgr(CIPHER_DEFAULT_CIPHER,CIPHER_DEFAULT_DIGEST,5,true);
    mgr.debug(true);

    std::string out = mgr.decrypt(in,”password”,salt );
    printf( “decrypted username = %s \n”, out.c_str());
    }

    void testEncrypt()
    {
    std::string salt = “”;
    Cipher mgr(CIPHER_DEFAULT_CIPHER,CIPHER_DEFAULT_DIGEST,5,false);
    mgr.debug(true);

    std::string in = “hello”;
    std::string out = mgr.encrypt(in,”password”,salt );
    printf( “password = %s \n”, out.c_str());
    }

    int main(int argc, char *argv[])
    {
    testDecrypt();
    testEncrypt();

    return 0;
    }

    question 1) like this it works.. if i flip the testEncrypt(); and testDecrypt(); around in sequence i get a

    ../src/cipher.cc:368: FCT decode_cipher
    terminate called after throwing an instance of ‘std::runtime_error’
    what(): EVP_DecryptFinal_ex() failed
    Aborted

    question2) why do i need to add a “\n” to the base64 encoded in string in testDecrypt to get it to work ?

    1. The run time error is occurring because your ciphertext fits into a 64 byte block.

      The reason that you have to add the new line because of an implementation artifact of the OpenSSL base64 processing. I have no idea why they did that.

      See Mihal Todor’s comments for more details.

  3. I have been playing with your Cipher library in order to encrypt some strings with AES for a small project and I think I ran into a bug.

    For example, by running the code below:

    I get the following error:

    I am compiling on the latest version of Ubuntu using GCC 4.7.3 with the libssl-dev package installed.

    I traced the error down to your decode_base64(…) function, which seems to malfunction if it passes to OpenSSL a base64 encoded string that doesn’t contain new lines. This happens when the ciphertext is small enough to fit in a single base64 block, and, thus, encode_base64(…) does not place any new lines in it. Apparently, the block size of base64, as implemented in OpenSSL, is 64 characters.

    I managed to come up with a fix, by adding the following code in decode_base64(…), right after BIO* b64 = BIO_new(BIO_f_base64());

    Ideally, I think both decode_base64(…) and encode_base64(…) should set the BIO_FLAGS_BASE64_NO_NL flag by default, such that the resulting base64 string doesn’t contain any new lines. This behavior can be achieved with the ‘-A’ switch for the openssl enc command line utility.

    The fact that OpenSSL requires a special flag to be able to decode a base64 string without new lines in it makes me sad. It’s just not possible for anybody to use their API correctly.

    Best regards,

    Mihai Todor

Leave a Reply