9

Rails 7 adds encryption to ActiveRecord

 3 years ago
source link: https://blog.saeloun.com/2021/06/09/rails-7-add-encryption-to-active-record
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Rails 7 adds encryption to ActiveRecord

Jun 9, 2021 , by Mayank Khanna 1 minute read

Before Rails 7, we used a lot of gems like attr_encrypted to encrypt and decrypt data in Active record models.

Let’s take an example of a User model, where we want to store the email in an encrypted format.

class User < ApplicationRecord
  validates_presence_of :email
end

Previously, using attr_encrypted gem we would do something like this:

class User < ApplicationRecord
  validates_presence_of :email
  attr_encrypted :email, key: :encryption_key
end

This increases the dependency on third-party gem for critical functionality like encryption.

To handle this problem, Rails 7 adds encrypted attributes to ActiveRecord models.

Basic setup

  • Firstly, we need to add some keys to our Rails credential file. Run the following command to generate the key set:
$ bin/rails db:encryption:init
  • Specify the attributes we need to encrypt. This happens at the model level:
# app/models/user.rb
class User < ApplicationRecord
  encrypts :email
  validates_presence_of :email
end

Usage

The library will transparently encrypt email before saving it into the database, and will decrypt it when retrieving its value.

User.create email: "[email protected]"

# INSERT INTO `users` (`email`) VALUES ('{\"p\":\"n7J0/ol+a7DRMeaE\",\"h\":{\"iv\":\"DXZMDWUKfp3bg/Yu\",\"at\":\"X1/YjMHbHD4talgF9dt61A==\"}}')

Deterministic and Non-Deterministic encryption

  • By default, ActiveRecord Encryption uses a non-deterministic approach for encryption. That means encrypting the same email twice will result in 2 different ciphertexts. It is better for security purposes, but it makes querying the database impossible. So we can use the deterministic approach to resolve this issue.
# app/models/user.rb
class User < ApplicationRecord
  encrypts :email, deterministic: true
  encrypts :phone_number
end

After this if we query the model normally like:

User.find_by(email: "[email protected]")
User.find_by(phone_number: "9911223344")

Since we did not set deterministic: true for the phone_number attribute, the query fails to find the user.

Custom Encryption methods

Rails 7 uses the EncryptableRecord concern to perform encryption and decryption when saving and retrieving values from the database. The main components of an encryption system are:

  • Encryptor - responsible for encrypting/decrypting data.
  • Cipher - the encryption algorithm (Aes 256 GCM)
  • KeyProvider - serves encryption and decryption keys
  • MessageSerializer - in charge of serializing and deserializing encrypted Message.

These components can be customized according to the needs by modifying the respective settings in the config file like:

config.active_record.encryption.encryptor = MyEncryptor.new

For more details, refer to this pull request.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK