# Playing with symmetric encryption algorithms in Ruby

In the times where data privacy is a headline every week it is good for software developers to have an understanding of encryption and programming.

For Rubyists the standard library of Ruby offers the **OpenSSL::Cipher **class to use symmetric encryption in Ruby code. Symmetric encryption means that both users who want to communicate are using the same key. This is different to asymmetric encryption where both users do not share the same key.

## Basics of symmetric encryption algorithms

Lets get right into it and fire up our **irb**. We need to require the openssl library to use its functionalities.

`> require 'openssl'`

=> true

Lets see what kind of symmetric algorithms the Ruby OpenSSL library offers.

`> puts OpenSSL::Cipher.ciphers`

As we can see Ruby offers a few algorithms in different varieties. Most ciphers are given using the following format:

`<name>-<key length>-<mode>`

Lets take a few as examples:

- Data Encryption Standard (DES) is a widely used encryption algorithm. Today it is not considered as secure and should not be used anymore.
- Rivest Cipher/Ron’s Code (RC) is a different symmetric algorithm. It is also considered as unsecure and should not be used anymore. (see this)
- Advanced Encryption Standard (AES) is a symmetric encryption algorithm which is widely used today and counts as secure

Since AES is considered as secure we will use it as our algorithm for now.

AES comes with different key bit lengths: 128, 192, 256. The higher the key length is the harder it is to brute force it (try all possible combinations). Eventhough AES128 counts as secure today computers are getting more and more powerful. To ensure that our code will stay secure for a longer period we will use AES256 for our following examples.

The different modes of encryption algorithms is out of the scope of this blog post so we will not take a deeper look at them. Just note that encryption algorithms can use different modes to encrypt data.

## Using OpenSSL::Cipher

Let’s create a new instance of a AES256 cipher using the **CBC** mode (as stated above: just ignore the mode since it is not relevant for these examples)

`> cipher = OpenSSL::Cipher::AES256.new :CBC`

After obtaining a cipher instance we have to set it to decryption or encryption mode:

`> cipher.encrypt`

Normally a cipher needs a key and an initialization vector to encrypt and decrypt a message. The initialization vector should be a random number. After generation it can be transmitted openly and does not need to be kept privately. The algorithm needs an initialization vector (IV) and the key for its encryption process.

**OpenSSL::Cipher **provides a method for generating an IV and should be used to save some hassle.

`> iv = cipher.random_iv`

This line does not only generate a random IV and sets it to **iv **but also sets the initialization vector for this cipher instance.

The key is where things get actually interesting. There are different ways to generate keys. One way of course would be to let the computer generate a random key.

But a user might want to set the key by himself. A problem is that you cannot take a normal word like **SecretPassword** as your key since AES256 requires your key to be 256 bit long.

`> cipher.key = "SecretPassword"`

OpenSSL::Cipher::CipherError: key length too short

By executing the following line

`> "string".encoding`

#<Encoding:UTF-8>

we can see that a string in my current **irb **instance is using UTF-8 as encoding which means that one character equals 8 bits.

Simple math: 256 / 8 = 32. This means that we need a 32 character string as our key for the AES256 algorithm. Ever had a 32 character long password?

Now lets take a key which is long enough and encrypt some data.

`> cipher.key = "ThisPasswordIsReallyHardToGuess!"`

Now we have our IV and key set. Now we can encrypt some data.

`> cipher_text = cipher.update('This is a secret message') + cipher.final`

**cipher.update** takes a message and encrypts it using the IV and key given before. **cipher.final **adds the final part of the cipher text to the end of the encrypted message. This is needed if encrypted data is transmitted so the decrypter knows when the end of the message is reached.

## Decryption

Decrypting works like encrypting:

`> decipher = OpenSSL::Cipher::AES256.new :CBC`

> decipher.decrypt

> decipher.iv = iv # previously saved

> decipher.key = 'ThisPasswordIsReallyHardToGuess!'

> plain_text = decipher.update(cipher_text) + decipher.final

=> "This is a secret message"

## Different Keys

What if we wanted our key just to be **SecretPassword**?

Here we could use a hash. A hash takes something (like a file, a string, …) and turns it into a fixed number of characters. This fixed number is specified by the hash algorithm which is being used.

In our case we want a 256 bit key so we need a hash function which creates 256 bit hashes. For this we can use the SHA-256 hash algorithm.

In Ruby we can use the SHA-256 hash algorithm using the **digest** library.

`> key = Digest::SHA256.digest 'SecretPassword'`

This line turns **SecretPassword** into a 256 bit hash which we can then use as a key for our AES encryption.

I hope this little post could give some insights in the world of symmetric encryption. We could not go deep into many aspects of symmetric encryption since it is out of scope for a simple blog post. But if anybody is interested feel free to leave a comment and I can write about a certain topic more specifically.