Basics of cryptography with OpenSSL

OpenSSL became publicly known (unfortunately) for the wrong reasons. Their development team got the typical backlash that System Administrators usually get: if everything is working fine nobody cares, as soon as something bad happens everybody loses their mind. I'm obviously talking about the Heartbleed bug. Before Heartbleed was found, it was estimated that 61% of all Apache servers used OpenSSL to handle TLS/SSL connections. As soon as it was found a lot of people freaked out. Successfully using this exploit could allow an attacker to read a target server memory, extract its private key and ultimately mount a man-in-the-middle attack . On the other hand, OpenSSL development team consisted of 11 contributors and a budget of less than $1 million a year (most of it from donations). In a world where even large Corporations, with almost unlimited resources, consistently release buggy software, a team of eleven developers should be allowed to make a few mistakes.

A few years passed and now it's water under the bridge. The original team eventually fixed this bug, while others forked OpenSSL source code and made the fixes themselves ([LibreSSL(http://www.libressl.org/)), and some got inspired by the original source code to created their own version (boringSSL).

Whatever on this blog post I want to step back a little and provide a quick overview of the basics of cryptography. There are tons of articles out there that explain every concept of cryptography in detail. However, I'm not a Mathematician, so the most you could get out of me is a blunt explanation. All that I want to show you is how can you use OpenSSL command line to encrypt and decrypt a file using symmetric and asymmetric cryptography.

Let's start to explain the difference between symmetric and asymmetric encryption. Imagine the following scenario: Edward wants to send confidential information to Laura. If they choose to use symmetric encryption, both of them need to have the exactly the same key to encrypt and decrypt messages. With asymmetric encryption, before any information is sent, Laura must generate a public and private key combination. Laura will keep the private key to herself and store it somewhere safe. Then Laura will send the public key to Edward, Edward will use the Laura's public key to encrypt the sensitive information he wants to share with Laura. Then Edward sends the encrypted information to Laura and Laura uses her private key to decrypt the information. In a very simplistic way, public key is used to encrypt and the private key to decrypt. If I correctly recall, asymmetric encryption was used by Edward Snowden and Laura Poitras to talk about NSA practices and leak confidential documents. If you haven't seen it, I strong recommend watching HBO's documentary Citizenfour highlights how Edward Snowden orchestrated the leak. But enough about theory, let's do it ourselves.

Download the OpenSSL binaries compiled for Windows at https://indy.fulgan.com/SSL/openssl-1.0.2h-x64_86-win64.zip. Once you have it, navigate to the directory where you extracted OpenSSL binaries and run "openssl.exe version" to check what version you're using. On this blog post I'm going to use version 'OpenSSL 1.0.2h 3 May 2016'. Most likely you will also have to create a configuration file, otherwise every time OpenSSL is executed the following warning might be displayed: 'WARNING: can't open config file: /usr/local/ssl/openssl.cnf'. You can download a sample configuration file from Oracle's website. Save it in 'C:\usr\local\ssl\openssl.cnf', update it with proper directory references (target existing directories) and you're good to go.

If you are running Windows 10 with Anniversary Update (version 10.0.10586 or above), you can use Bash on Ubuntu on Windows. Scott Hanselman have a great walk-thought video on how to run Linux on Windows 10. OpenSSL should come pre-installed. As usual I tend to prefer PowerShell, so for this post I will be calling 'OpenSSL.exe' from PowerShell. But the commands will be same, no matter what 'prompt' you prefer.

Ok, let's create a new text file (named 'plain.txt') to test encryption. Keep in mind that I'm using PowerShell.

Set-Content -Path 'plain.txt' -Value 'Testing encryption with OpenSSL'

Now let's use AES-256 (symmetric encryption) to encrypt our plain text file.

.\openssl.exe enc -aes-256-ctr -in plain.txt -out aesEncryptedTxt.bin

You will be prompted to enter a password. I will be using 'test1' as our password (just for future reference). To decrypt the file, use the following command (passing password as an argument is optional).

.\openssl.exe enc -aes-256-ctr -d -in aesEncryptedTxt.bin -pass pass:test1

Easy right? As you might have noticed, the only thing protecting our text is the selected cipher and provided password. Realistically this is not good enough. For the sake of simplicity, I'm not providing a AES key. Just keep in mind that a AES key will add an additional level of protection in order to prevent brute-force attacks.

For asymmetric encryption let's start by generating a pair of 2048 bits, RSA public/private key.

.\openssl.exe genrsa -out myKeyPair.pem 2048 

As previously mentioned, the private key must be kept in a secure place. Even better if it's encrypted. Let's use AES-256 to encrypt our key pair (you will be prompted to enter a password).

.\openssl.exe rsa -in myKeyPair.pem -aes-256-ctr -out myKeyPair-Encrypted.pem 

Now your friend Edward wants to send you a confidential file. He asks you for a public key. Here's how we can generate a public key for Edward.

.\openssl.exe rsa -in myKeyPair-Encrypted.pem -pubout -out pubKeyForEdward.pem 

The key distribution problem is another problem by itself. For the sake of simplicity let's skip that part. For now, imagine that's you gave Edward a flash drive with the public key. Edward will now use your public key to encrypt the file he wants to send. Using your public key, Edward will be able to encrypt the file, but won't be able to decrypt it (but who cares, he has the original file).

.\openssl.exe rsautl -encrypt -in plain.txt -pubin -inkey pubKeyForEdward.pem -out edwardEncryptedFile.bin  

Edward has sent the encrypted file to you, to decrypt it just run:

.\openssl.exe rsautl -decrypt -in edwardEncryptedFile.bin -inkey myKeyPair-Encrypted.pem 

Simple right? Honestly this was incredibly over-simplified. In my defense, most tutorials about cryptography dump a ton of information on newcomers which can be quite overwhelming. My approach is the opposite, by providing the basics I want the reader to feel comfortable and spike his interest on this subject. Just keep in mind that I purposely skipped some concepts for the sake of simplicity.

OpenSSL logo