Rails 7 adds encryption to ActiveRecord
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.
Rails 7 adds encryption to ActiveRecord
Jun 9, 2021 , by Mayank Khanna 1 minute readBefore 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 thedeterministic
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.
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK