AttrDigest
AttrDigest provides functionality to store a hash digest of an attribute using Argon2.
Argon2 is a password-hashing function that summarizes the state of the art in the design of memory-hard functions and can be used to hash passwords for credential storage, key derivation, or other applications. It is the official winner and recommendation of the Password Hashing Competition (PHC) which ran between 2013 and 2015.
This Gem uses the Ruby Argon2 Gem which provides FFI bindings, and a simplified interface, to the Argon2 algorithm.
AttrDigest provides similar functionality to Rails has_secure_password, but permits any number attributes to be hashed in a model, and obviously you're not limited to just the password attribute.
Installation
To install add the following line to your Gemfile:
gem 'attr_digest',
And run bundle install.
Dependencies
Runtime:
- activerecord (>= 4.2.6, ~> 5.0.0)
- activesupport (>= 4.2.6, ~> 5.0.0)
- argon2 (~> 1.1.0)
Development/Test:
- rake (~> 10.5)
- rspec (~> 3.4)
- sqlite3 (~> 1.3)
- simplecov (~> 0.11.2)
- factory_girl (~> 4.5)
Compatibility
Tested with Ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-darwin15] against ActiveRecord 5.0.0 on Mac OS X El Capitan 10.11.5 (15F34).
Argon2 requires Ruby 2.2 minimum and an OS platform that supports Ruby FFI Bindings, so unfortunately Windows is out.
Usage
Attributes to be digested are declared using the attr_digest class method in your model:
ActiveRecord::Schema.define do
create_table :users, force: true do |t|
t.string :security_question, null: false
t.string :security_answer_digest, null: false
end
end
class User < ActiveRecord::Base
attr_digest :security_answer
end
AttrDigest automatically creates the #security_answer getter and #security_answer= setter. The setter creates a digest of the value provided and stores it in the security_answer_digest column.
AttrDigest also defines the method authenticate_security_answer(value) which returns false if the value given does not correspond to the saved digest, or returns true if it does.
Validations
AttrDigest adds some default validations. Using the example above:
- it creates a
confirmationvalidation onsecurity_answer, but only ifsecurity_answeris given (for confirmation validations see ActiveRecord Validations). - it creates a
presencevalidation onsecurity_answerbut only oncreate. - it creates a
presencevalidation onsecurity_answer_confirmationbut only ifsecurity_answerhas been given; and - it raises an
exceptionifsecurity_answer_digestis empty oncreate.
You can disable all validations by passing false to the validations option:
attr_digest :security_answer, validations: false
Case Sensitivity
If you want values passed to be case insensitive, you can pass false to the case_sensitive option:
attr_digest :security_answer, case_sensitive: false
Then differing cases will match, e.g. pizza will match PizzA.
Confirmations
If you prefer to skip confirmations for the attribute you are hashing, you can pass false to the confirmation option:
attr_digest :security_answer, confirmation: false
Protected Digest Setter
If you want to prevent the attribute's digest being set directly, you can include the protected option:
attr_digest :security_answer, protected: true
The attribute's digest is not protected from direct setting by default.
Tests
Tests are written using Rspec, FactoryGirl and Sqlite3. There are 31 examples with 100% code coverage.
To run the tests, execute the default rake task:
bundle exec rake
Roadmap
I would like to add the ability to pass a secret to the Argon2 hasher. This functionality exists in the Ruby Argon2 Gem.
Contributing
- Fork it
- Create your feature branch (
git checkout -b my-new-feature) - Commit your changes (
git commit -am 'Add some feature') - Push to the branch (
git push origin my-new-feature) - Create new Pull Request
Credit
I would like to thank Panayotis Matsinopoulos for his has_secure_attribute gem which provided a lot of the inspiration and framework for AttrDigest.
License
The gem is available as open source under the terms of the MIT License.
Copyright
Copyright 2016 Brightcommerce, Inc.