Encrypting files with OpenSSL

OpenSSL is a great toolkit for working with TLS/SSL protocols, however it can also be used for several other cryptography related tasks. This post is going to quickly go over using OpenSSL to encrypt and decrypt files with a symmetric key.

Selecting an algorithm

The available cipher algorithms will depend on the exact version of OpenSSL you're using and compile time options, the list-cipher-algorithms command can be used to list available ciphers:

$ openssl list-cipher-algorithms
AES-128-CBC
AES-128-CBC-HMAC-SHA1
AES-128-CFB
AES-128-CFB1
AES-128-CFB8
AES-128-CTR
AES-128-ECB
AES-128-OFB
...

Unfortunately the enc command requires a slightly different format. Details of the available ciphers can be found in the enc(1) man page. Alternatively you can run enc with and unsupported option (for example openssl enc -help) to print a list of cipher options:

$ openssl enc -help
unknown option '-help'
options are
-in <file>     input file
-out <file>    output file
-pass <arg>    pass phrase source
-e             encrypt
-d             decrypt
-a/-base64     base64 encode/decode, depending on encryption flag
-k             passphrase is the next argument
-kfile         passphrase is the first line of the file argument
-md            the next argument is the md to use to create a key
                 from a passphrase. See openssl dgst -h for list.
-S             salt in hex is the next argument
-K/-iv         key/iv in hex is the next argument
-[pP]          print the iv/key (then exit if -P)
-bufsize <n>   buffer size
-nopad         disable standard block padding
-engine e      use engine e, possibly a hardware device.
Cipher Types
-aes-128-cbc               -aes-128-cbc-hmac-sha1     -aes-128-cfb
-aes-128-cfb1              -aes-128-cfb8              -aes-128-ctr
-aes-128-ecb               -aes-128-gcm               -aes-128-ofb
...

For the rest of this post I'm going to use a AES with a 128 bit key and Cipher Block Chaining (aes-128-cbc), however the process of encrypting and decrypting files using the enc command should be very similar for other algorithms.

Encrypting files

A simple test file can be created with the following command:

$ echo hello world > plain-text.txt

The file can then be encrypted with a command similar to the following:

$ openssl enc -e -aes-128-cbc -in plain-text.txt -out cipher-text.txt
enter aes-128-cbc encryption password:
Verifying - enter aes-128-cbc encryption password:

It's important that the password used to encrypt the file is suitably complex to avoid brute force attacks. The resulting cipher text file will look something like the following:

$ xxd cipher-text.txt
0000000: 5361 6c74 6564 5f5f 5537 e53f 5beb 8d3f  Salted__U7.?[..?
0000010: 87ed 1b2d 7f8a 002d 76d7 84c4 26d6 fd74  ...-...-v...&..t

Note: by default a salt will be used with the password to generate the encryption key. The cipher text file will have a Salted__ signature to indicate this, followed by an eight byte salt.

Decrypting files

To decrypt the cipher text the -d option can be used:

$ openssl enc -d -aes-128-cbc -in cipher-text.txt -out decrypted.txt
enter aes-128-cbc decryption password:
$ cat decrypted.txt
hello world

It's worth noting that invalid passwords will be detected, and a non-zero error code is returned:

$ openssl enc -d -aes-128-cbc -in cipher-text.txt -out decrypted.txt
enter aes-128-cbc decryption password:
bad decrypt
139871004383136:error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt:evp_enc.c:604:
$ echo $?
1