Data Encryption with Rails 7

Reading Time: 4 minutes

There are massive amounts of sensitive information managed and stored online in the cloud or connected servers. Encryption uses cybersecurity to defend against brute force and cyberattacks, including malware and ransomware. Read this article to learn about how Rails 7 works with Data Encryption.

How does encryption work?

  • Data encryption works by securing transmitted digital data in the cloud and computer systems. In fact, there are three kinds of digital data:
    • data in use,
    • transmitted data or in-flight data (data in transit)
    • and stored digital data or data at rest.
  • Modern encryption algorithms have replaced the outdated Data Encryption Standard to protect data. Specifically, these algorithms protect information and fuel security initiatives including integrity, authentication, and non-repudiation.

  • Also, algorithms first authenticate a message to verify the origin. Next, they check the integrity to verify that contents are unchanged.

  • Finally, the non-repudiation initiative stops sends from denying legitimate activity.

What should an encryption strategy cover?

  • Integrity: ability to ensure the inalterability of a document, i.e. that the document sent is the same as the one received.

  • Authenticity: it proves the identity of the person who has signed the document, i.e. that the person who signs is who they say they are.

  • Confidentiality: the document is accessible only to authorized persons.

  • Non-repudiation: once the document is signed, the signatory cannot deny its authorship.

Types of Data Encryptation

There are several different encryption methods, each developed with different security and security needs in mind. Then again, the two main types of data encryption are asymmetric encryption and symmetric encryption.

Asymmetric encryption

Asymmetric encryption, also known as Public-Key Cryptography, encrypts and decrypts data using two separate cryptographic asymmetric keys. Indeed, these two keys are known as “public key” and “private key”.

Common asymmetric encryption methods

  • RSA: RSA, named after computer scientists Ron Rivest, Adi Shamir, and Leonard Adleman; it is a popular algorithm used to encrypt data with a public key and decrypt with a private key for secure data transmission.
  • Public key infrastructure (PKI): PKI is a way of governing encryption keys through the issuance and management of digital certificates.

Symmetric encryption

On the contrary, symmetric encryption is a type of encryption where only one secret symmetric key is used to encrypt the plaintext and decrypt the ciphertext.

Common symmetric encryption methods:

  • Data Encryption Standards (DES): DES is a low-level encryption block cipher algorithm that converts plain text in blocks of 64 bits and converts them to ciphertext using keys of 48 bits.
  • Triple DES: Triple DES runs DES encryption three different times by encrypting, decrypting, and then encrypting data again.
  • Advanced Encryption Standard (AES): AES is often referred to as the gold standard for data encryption and it is used worldwide as the U.S. government standard (possibly in rails 7).
  • Twofish: Twofish is considered one of the fastest encryption algorithms and it is free to use.

Symmetric key ciphers are valuable because

  • It is relatively inexpensive to produce a strong key for these ciphers.
  • The keys tend to be much smaller for the level of protection they afford.
  • The algorithms are relatively inexpensive to process.

Using encryption in Rails 7

  • Active Record supports application-level encryption.
  • It works by declaring which attributes should be encrypted and seamlessly encrypting and decrypting them when needed.
  • The encryption layer sits between the database and the application.
  • The application will access unencrypted data, but the database will store it encrypted.

Start generating a Rails 7 App

To do this, from your favourtite terminal and having Rails properly installed run next command:

rails new cryptoapp

Then, once inside the application folder, generate the keys that we need to start encrypting:

rails db:encryption:init

Then, this command should generate some keys with the next pattern:

  primary_key: somekey98u302umxmzm09i209i321m30
  deterministic_key: somekeyKwIilShkJ0IRPM43ldEFW1
  key_derivation_salt: somekey4rx8EQ6Ff2ETMkVEa9Aq5DDG5ngrWvHv

In order to be able to start encrypting, we should add these new keys into the encrypted credentials file by running the command:

rails credentials:edit

Private keys

After this, let’s save changes and then start generating a scaffold and run migrations to play with this feature:

rails g scaffold Post body:text
rails db:migrate

Now we can edit our current Postmodel to look like this:

class Post < ApplicationRecord
  encrypts :body

Let’s create our first Post and see what happens; in the rails console run the next line:

Post.create(body: &#039;hello world&#039;)

Observe that the logs looks like this:

(0.5ms)  SELECT sqlite_version(*)
  TRANSACTION (0.0ms)  begin transaction
  Post Create (0.4ms)  INSERT INTO "posts" ("body", "created_at", "updated_at") VALUES (?, ?, ?)  [["body", "{\"p\":\"NbmPOZ8UkCyaSXM=\",\"h\":{\"iv\":\"rvHQv9lFF8+D4Gjq\",\"at\":\"s65cbgU5yAuNmtARWnVbQg==\"}}"], ["created_at", "2021-12-22 17:45:06.369384"], ["updated_at", "2021-12-22 17:45:06.369384"]]
  TRANSACTION (1.0ms)  commit transaction
=> #<Post:0x00007fd77cb10048 id: 1, body: "hello world", created_at: Wed, 22 Dec 2021 17:45:06.369384000 UTC +00:00, updated_at: Wed, 22 Dec 2021 17:45:06.369384000 UTC +00:00>

As we can see, the logs only show the encrypted message, not the original, this is because that was submitted to the database.

By default, Rails uses non-deterministic approach, if you want to query on these attributes, we should use deterministic approach as in the Post model, otherwise you are never going to get the results, so let’s apply the deterministic approach:

class Post < ApplicationRecord
  encrypts :body, deterministic: true

Then, we should be able to query on those attributes as usual:

Post.where(body: &#039;hello world&#039;)

The output could look like this:

Post Load (0.2ms)  SELECT "posts".* FROM "posts" WHERE "posts"."body" = ?  [["body", "{\"p\":\"kshzlrlUbCC5gy0=\",\"h\":{\"iv\":\"d7rfcOy4FWRCFfaR\",\"at\":\"68zgkDeIlCFC0XMILOp+kg==\"}}"]]
=> [#<Post:0x00007fd77748e210 id: 2, body: "hello world", created_at: Wed, 22 Dec 2021 17:50:39.592176000 UTC +00:00, updated_at: Wed, 22 Dec 2021 17:50:39.592176000 UTC +00:00>]

To sum up

For more information in regards to encryption in Rails visit Active Record Encryption documentation and ActiveSupport::MessageEncryptor if you want to play with this class to encrypt messages as well.

It is possible to encrypt in previous versions of Rails too, you can check the gem Lockbox and see how this could be done.

You May Also Like