Skip to content

encrypt & decrypt Active Record attributes with Message Encryptor

License

Notifications You must be signed in to change notification settings

kuntoaji/enkrip

Folders and files

NameName
Last commit message
Last commit date

Latest commit

7ed4a76 Â· Jul 16, 2019

History

14 Commits
Oct 28, 2018
Oct 28, 2018
Oct 28, 2018
Nov 1, 2018
Oct 28, 2018
Oct 28, 2018
Oct 28, 2018
Jul 16, 2019
Oct 27, 2018
Oct 28, 2018

Repository files navigation

Gem Version

Enkrip

Encrypt & decrypt Active Record's model attributes with ActiveSupport::MessageEncryptor. See Enkrip Example Rails Application for demo.

Goals

  • Seamlessly encrypt and decrypt value for both string and numeric attribute
  • Compatible with Active Model validation
  • Automatically convert numeric attributes to desired format after decryption

Limitations

  • All attributes that are defined in numeric_attributes will be forced to use UTF-8 encoding
  • Enkrip requires Active Record 5.2 or newer
  • Does not compatible with activerecord-import
  • In some cases, does not compatible with ActiveRecord::Attributes

Installation

Add enkrip to your Rails app’s Gemfile and run bundle install:

gem 'enkrip'

Configuration

After installation, you need to define ENKRIP_LENGTH, ENKRIP_SALT, and ENKRIP_SECRET environment variables:

# example
# 32 is default value from ActiveSupport::MessageEncryptor.key_len
export ENKRIP_LENGTH=32

# you can generate this value with SecureRandom.random_bytes(YOUR_ENKRIP_LENGTH)
export ENKRIP_SALT=random_salt_with_length_32

# 32 random characters
export ENKRIP_SECRET=random_secret_with_length_32

Usage

Use text data type for encrypted attributes

# migration

class CreatePosts < ActiveRecord::Migration[5.2]
  def change
    create_table :posts do |t|
      t.text :my_string
      t.text :my_numeric

      t.timestamps
    end
  end
end

After run the migration, define your encrypted attributes

# Active Record model

class Post < ActiveRecord::Base
  include Enkrip::Model

  enkrip_configure do |config|
    config.string_attributes << :my_string
    config.numeric_attributes << :my_numeric
    config.purpose = :example # optional, default is nil
    config.convert_method_for_numeric_attribute = :to_f # optional, default is to_i
    config.default_value_if_numeric_attribute_blank =  0.0 # optional, default is 0
  end

  validates :my_numeric, numericality: { greater_than: 0 }
  validates :my_string, presence: true
end

You can check encrypted value from rails console with raw query

# Rails 5.2 console
post = Post.new => #<Post id: nil, my_string: nil, my_numeric: nil, created_at: nil, updated_at: nil>
post.valid? # => false
post.errors.full_messages # => ["My numeric must be greater than 0", "My string can't be blank"]

post.my_string = "aloha" # => "aloha"
post.my_numeric = 5 # => 5
post.save # => true

raw = ActiveRecord::Base.connection.exec_query 'SELECT my_string, my_numeric FROM posts limit 1'

raw.rows.first[raw.columns.find_index('my_string')]
# => "TUVQcnRBck5oYzMvRlRZUWR3Mzlzdz09LS1tZ09xNGNYbnkzdFc2d1duMEIrdUdBPT0=--ffae1f04753ca5c636915746a4c6fccf81897138"

raw.rows.first[raw.columns.find_index('my_numeric')]
# => "TkdSbURRNzVMbUF6MjF0bjI2ZEtmQT09LS1rRHhqQ2xpWGhYaHBoRlhCRnVZSmh3PT0=--74e45e6c96df78258a1731994a71a74c5047d655"

post.reload
post.my_string # => "aloha"
post.my_numeric # => 5

Usage For non-Active Record Model

You can use Enkrip::Engine.encrypt and Enkrip::Engine.decrypt to encrypt and decrypt a value.

my_string = 'hello world'

encrypted_my_string = Enkrip::Engine.encrypt my_string
# => "MzZ1M0RDSWdQQ0VaRVJXT3NBYlVTWExWVnVSbXNBeXRMSC9wYWdoeW5Ddz0tLVNVT2l6NDJCd1ZxbW1lYnl2eC9PakE9PQ==--c7436c403595c18fef802a51be29f73d5bb73f19"

Enkrip::Engine.decrypt encrypted_my_string
# => "hello world"

You can pass purpose to the Enkrip::Engine.decrypt and Enkrip::Engine.encrypt.

# you can pass purpose parameter, default purpose is nil.
second_string = 'hello world 2'
another_encrypted_my_string = Enkrip::Engine.encrypt second_string, purpose: :example_purpose

Enkrip::Engine.decrypt another_encrypted_my_string, purpose: :random_purpose # => nil
Enkrip::Engine.decrypt another_encrypted_my_string # => nil
Enkrip::Engine.decrypt another_encrypted_my_string, purpose: :example_purpose # => "hello world 2"

License

Enkrip is released under the MIT License.