Transcryptor provides utility functions to help migrate records encrypted with
attr_encrypted
from one
encryption configuration to another.
Installation
Add this line to your application’s Gemfile:
gem 'transcryptor', github: 'riboseinc/transcryptor'
And then execute:
bundle
Or install it yourself as:
gem install transcryptor
Usage
Given:
-
you have already set up tables to be encrypted with
attr_encrypted
, -
you’d like to migrate your columns from:
(
algorithm1
,iv1
,salt1
,key1
)to
(
algorithm2
,iv2
,salt2
,key2
)where:
-
algorithm
can beaes-256-cbc
,aes-256-gcm
or any others thatattr_encrypted
supports, -
salt
can be optional, -
iv
can be optional (!!).
-
Then:
-
Create a migration like so:
class ReencryptUsersAndDocumentsWithNewKeys < ActiveRecord::Migration def transcryptor Transcryptor.init(self) end # +keyifier+ mirrors the functionality provided by the :key Proc in # attr_encrypted. # NOTE: Has to return the entire Hash. # def old_keyifier -> opts { opts[:key] = ENV['old_master_encryption_key'] + opts[:key] opts } end def new_keyifier -> opts { opts[:key] = ENV['new_master_encryption_key'] + opts[:key] opts } end # Define the current DB schema for Transcryptor. # Format: # { # <table_i>: { # id_column: <the column name for record id>, # columns: { # <column_i>: { # prefix: <attr_encrypted prefix string (optional)>, # suffix: <attr_encrypted suffix string (optional)>, # key: <the column storing the key to encrypt column_i>, # }, # } # }, # } # def table_column_spec { users: { id_column: :id, columns: { email: { prefix: 'encrypted_', key: :ekey, }, birthday: { prefix: 'encrypted_', key: :ekey, }, } }, documents: { id_column: :id, columns: { passphrase: { prefix: 'secret_', key: :enc_key, }, } }, } end # # Run transcryptor.updown_migrate() for both #up and #down. # Give it: # - the table-column specification, # - the old encryption configuration (at least any one of: algorithm, iv, # salt, key) # - the new encryption configuration (at least any one of: algorithm, iv, # salt, key) # - optional params-modifying Proc before passing to Encryptor.decrypt (used # by attr_encrypted) # - optional params-modifying Proc before passing to Encryptor.encrypt (used # by attr_encrypted) # def up transcryptor.updown_migrate( table_column_spec, { algorithm: 'aes-256-cbc', decode64_value: true, }, { algorithm: 'aes-256-gcm', encode64_iv: true, encode64_value: true, iv: true, }, old_keyifier, new_keyifier, ) end def down transcryptor.updown_migrate( table_column_spec, { algorithm: 'aes-256-gcm', decode64_iv: true, decode64_value: true, }, { algorithm: 'aes-256-cbc', iv: false, salt: false, encode64_value: true, insecure_mode: true, }, new_keyifier, old_keyifier, ) end
-
Run
bundle exec db:migrate
-
Done!
Development
After checking out the repo, run bin/setup
to install dependencies. Then, run
rake spec
to run the tests. You can also run bin/console
for an interactive
prompt that will allow you to experiment.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/riboseinc/transcryptor. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.
License
The gem is available as open source under the terms of the MIT License.