Protect provides searchable encryption for your ActiveRecord models.
With Protect you never need trade security for queryability - you can have both!
Protect is compatible with the following databases:
- Postgres (self-hosted / cloud-hosted, e.g. Amazon RDS)
- MySQL (planned)
- MS SQL (planned)
- CockroachDB (planned)
Add this line to your application’s Gemfile:
gem "cipherstash-protect"Run:
bundle installRun rake protect:generate_keys to generate the required local keys to use Protect and copy over to your Rails credentials file, or add as environment variables.
1. Install the Protect custom types:
The first thing to do is install the Protect custom types into your database.
This is achieved by creating a new Rails migration the usual way, and adding the following code:
class AddProtectDatabaseExtensions < ActiveRecord::Migration[7.0]
def up
Protect::DatabaseExtensions.install
end
def down
Protect::DatabaseExtensions.remove
end
endThis migration adds in the custom type ore_64_8_v1.
2. Migration to add columns for encrypted data:
For each field you are encrypting, 2 columns need to be added.
One to hold the encrypted source data.
One to hold the encrypted queryable data.
Field names appended with _ciphertext hold the source encrypted data.
Field names appended with _secure_search hold the encrypted queryable data.
For a plaintext field named email, a migration to add in the encrypted columns would look like this:
class AddEncryptedFields < ActiveRecord::Migration[7.0]
def change
add_column :users, :email_ciphertext, :text
add_column :users, :email_secure_search, :ore_64_8_v1
end
endNote the custom type ore_64_8_v1 we installed in the previous step is used on the _secure_search column.
You are now ready to encrypt your existing plaintext data into the encrypted columns added in the previous step.
1. Update the model:
For each field that your are encrypting, update your model with secure_search followed by the field.
class User < ApplicationRecord
secure_search :email
end2. Run Rake task:
The encrypt Rake task will encrypt your plaintext data into the 2 columns added in the previous step.
The existing plaintext field remains as is for now.
Provide the model that you are encrypting to the Rake task.
Using bash:
rake protect:encrypt[User]Using zsh:
rake protect:encrypt\[User\]3. Update model:
After the Rake task has completed, update the model to ignore the plaintext field.
class User < ApplicationRecord
secure_search :email
# remove this line after dropping email column
self.ignored_columns = ["email"]
end4. Drop plaintext column:
Once satisfied that everything is working, create a migration to drop the plaintext column.