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.
Previously, using attr_encrypted
gem we would do something like this:
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:
- Specify the attributes we need to encrypt. This happens at the model level:
Usage
The library will transparently encrypt email
before saving it into the database,
and will decrypt it when retrieving its value.
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.
After this if we query the model normally like:
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.