Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

attr_encrypted-magicless

Package Overview
Dependencies
Maintainers
4
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

attr_encrypted-magicless

  • 1.3.42
  • Rubygems
  • Socket score

Version published
Maintainers
4
Created
Source

= attr_encrypted-magicless {}[https://travis-ci.org/estum/attr_encrypted]

Generates attr_accessors that encrypt and decrypt attributes transparently

It works with ANY class, however, you get a few extra features when you're using it with ActiveRecord.

== Installation

gem install attr_encrypted-magicless

== Usage

=== Basic

Encrypting attributes has never been easier:

class User include AttrEncrypted

attr_accessor :name
attr_encrypted :ssn, :key => 'a secret key'

def load
  # loads the stored data
end

def save
  # saves the :name and :encrypted_ssn attributes somewhere (e.g. filesystem, database, etc)
end

end

@user = User.new @user.ssn = '123-45-6789' @user.encrypted_ssn # returns the encrypted version of :ssn @user.save

@user = User.load @user.ssn # decrypts :encrypted_ssn and returns '123-45-6789'

The attr_encrypted method is also aliased as attr_encryptor to conform to Ruby's attr_ naming conventions. I should have called this project attr_encryptor but it was too late when I realized it ='(.

=== Adding required columns via database migration

By default, attr_encrypted uses the :single_iv_and_salt encryption mode for compatibility with previous versions of the gem. This mode uses a single IV and salt for each encrypted column. Create or modify your model to add a column with the encrypted_ prefix (which can be modified, see below), e.g. encrypted_ssn via a migration like the following:

create_table :users do |t| t.string :name t.string :encrypted_ssn t.timestamps end

For enhanced security, you can use the :per_attribute_iv_and_salt mode. This requires additional _salt and iv columns with the encrypted prefix as follows and generates a unique salt and IV per attribute:

create_table :users do |t| t.string :name t.string :encrypted_ssn t.string :encrypted_ssn_salt t.string :encrypted_ssn_iv t.string :domain t.timestamps end

This mode is enabled by specifying a value of :per_attribute_iv_and_salt via the :mode option as follows:

class User include AttrEncrypted attr_accessor :name attr_encrypted :ssn, :key => 'a secret key', :mode => :per_attribute_iv_and_salt end

Note that there are alternatives to storing the IV and salt in separate columns: for example, see here[https://github.com/attr-encrypted/attr_encrypted/issues/118#issuecomment-45806629]. Note that migration from the old encryption scheme to the new is nontrivial. One approach is described here[http://jjasonclark.com/switching_from_attr_encrypted_to_attr_encryptor], though these instructions describe the now-defunct attr_encryptor gem whose functionality has been merged into this project.

=== Specifying the encrypted attribute name

By default, the encrypted attribute name is encrypted_#{attribute} (e.g. attr_encrypted :email would create an attribute named encrypted_email). So, if you're storing the encrypted attribute in the database, you need to make sure the encrypted_#{attribute} field exists in your table. You have a couple of options if you want to name your attribute something else.

==== The :attribute option

You can simply pass the name of the encrypted attribute as the :attribute option:

class User include AttrEncrypted attr_encrypted :email, :key => 'a secret key', :attribute => 'email_encrypted' end

This would generate an attribute named email_encrypted

==== The :prefix and :suffix options

If you're planning on encrypting a few different attributes and you don't like the encrypted_#{attribute} naming convention then you can specify your own:

class User include AttrEncrypted attr_encrypted :email, :credit_card, :ssn, :key => 'a secret key', :prefix => 'secret_', :suffix => '_crypted' end

This would generate the following attributes: secret_email_crypted, secret_credit_card_crypted, and secret_ssn_crypted.

=== Encryption keys

Although a :key option may not be required (see custom encryptor below), it has a few special features

==== Unique keys for each attribute

You can specify unique keys for each attribute if you'd like:

class User include AttrEncrypted attr_encrypted :email, :key => 'a secret key' attr_encrypted :ssn, :key => 'a different secret key' end

==== Symbols representing instance methods as keys

If your class has an instance method that determines the encryption key to use, simply pass a symbol representing it like so:

class User include AttrEncrypted attr_encrypted :email, :key => :encryption_key

def encryption_key
  # does some fancy logic and returns an encryption key
end

end

==== Procs as keys

You can pass a proc/lambda object as the :key option as well:

class User include AttrEncrypted attr_encrypted :email, :key => proc { |user| user.key } end

This can be used to create asymmetrical encryption by requiring users to provide their own encryption keys.

=== Conditional encrypting

There may be times that you want to only encrypt when certain conditions are met. For example maybe you're using rails and you don't want to encrypt attributes when you're in development mode. You can specify conditions like this:

class User < ActiveRecord::Base attr_encrypted :email, :key => 'a secret key', :unless => Rails.env.development? end

You can specify both :if and :unless options. If you pass a symbol representing an instance method then the result of the method will be evaluated. Any objects that respond to :call are evaluated as well.

=== Custom encryptor

The Encryptor (see http://github.com/shuber/encryptor) class is used by default. You may use your own custom encryptor by specifying the :encryptor, :encrypt_method, and :decrypt_method options

Lets suppose you'd like to use this custom encryptor class:

class SillyEncryptor def self.silly_encrypt(options) (options[:value] + options[:secret_key]).reverse end

def self.silly_decrypt(options)
  options[:value].reverse.gsub(/#{options[:secret_key]}$/, '')
end

end

Simply set up your class like so:

class User include AttrEncrypted attr_encrypted :email, :secret_key => 'a secret key', :encryptor => SillyEncryptor, :encrypt_method => :silly_encrypt, :decrypt_method => :silly_decrypt end

Any options that you pass to attr_encrypted will be passed to the encryptor along with the :value option which contains the string to encrypt/decrypt. Notice it uses :secret_key instead of :key.

=== Custom algorithms

The default Encryptor uses the standard ruby OpenSSL library. It's default algorithm is aes-256-cbc. You can modify this by passing the :algorithm option to the attr_encrypted call like so:

class User include AttrEncrypted attr_encrypted :email, :key => 'a secret key', :algorithm => 'bf' end

Run openssl list-cipher-commands to view a list of algorithms supported on your platform. See http://github.com/shuber/encryptor for more information.

aes-128-cbc aes-128-ecb aes-192-cbc aes-192-ecb aes-256-cbc aes-256-ecb base64 bf bf-cbc bf-cfb bf-ecb bf-ofb cast cast-cbc cast5-cbc cast5-cfb cast5-ecb cast5-ofb des des-cbc des-cfb des-ecb des-ede des-ede-cbc des-ede-cfb des-ede-ofb des-ede3 des-ede3-cbc des-ede3-cfb des-ede3-ofb des-ofb des3 desx idea idea-cbc idea-cfb idea-ecb idea-ofb rc2 rc2-40-cbc rc2-64-cbc rc2-cbc rc2-cfb rc2-ecb rc2-ofb rc4 rc4-40

=== Default options

Let's imagine that you have a few attributes that you want to encrypt with different keys, but you don't like the encrypted_#{attribute} naming convention. Instead of having to define your class like this:

class User include AttrEncrypted attr_encrypted :email, :key => 'a secret key', :prefix => '', :suffix => '_crypted' attr_encrypted :ssn, :key => 'a different secret key', :prefix => '', :suffix => '_crypted' attr_encrypted :credit_card, :key => 'another secret key', :prefix => '', :suffix => '_crypted' end

You can simply define some default options like so:

class User include AttrEncrypted attr_encrypted_options.merge!(:prefix => '', :suffix => '_crypted') attr_encrypted :email, :key => 'a secret key' attr_encrypted :ssn, :key => 'a different secret key' attr_encrypted :credit_card, :key => 'another secret key' end

This should help keep your classes clean and DRY.

=== Encoding

You're probably going to be storing your encrypted attributes somehow (e.g. filesystem, database, etc) and may run into some issues trying to store a weird encrypted string. I've had this problem myself using MySQL. You can simply pass the :encode option to automatically encode/decode when encrypting/decrypting.

class User include AttrEncrypted attr_encrypted :email, :key => 'some secret key', :encode => true end

The default encoding is m* (base64). You can change this by setting :encode => 'some encoding'. See the Array#pack method at http://www.ruby-doc.org/core/classes/Array.html#M002245 for more encoding options.

=== Marshaling

You may want to encrypt objects other than strings (e.g. hashes, arrays, etc). If this is the case, simply pass the :marshal option to automatically marshal when encrypting/decrypting.

class User include AttrEncrypted attr_encrypted :credentials, :key => 'some secret key', :marshal => true end

You may also optionally specify :marshaler, :dump_method, and :load_method if you want to use something other than the default Marshal object.

=== Encrypt/decrypt attribute methods

If you use the same key to encrypt every record (per attribute) like this:

class User include AttrEncrypted attr_encrypted :email, :key => 'a secret key' end

Then you'll have these two class methods available for each attribute: User.encrypt_email(email_to_encrypt) and User.decrypt_email(email_to_decrypt). This can be useful when you're using ActiveRecord (see below).

=== ActiveRecord

If you're using this gem with ActiveRecord, you get a few extra features:

==== Default options

For your convenience, the :encode option is set to true by default since you'll be storing everything in a database.

== Note on Patches/Pull Requests

  • Fork the project.
  • Make your feature addition or bug fix.
  • Add tests for it. This is important so I don't break it in a future version unintentionally.
  • Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
  • Send me a pull request. Bonus points for topic branches.

FAQs

Package last updated on 09 Sep 2015

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc