├── .rspec ├── Rakefile ├── .yardopts ├── lib ├── devise-scrypt.rb └── devise │ └── encryptable │ └── encryptors │ ├── scrypt │ └── version.rb │ └── scrypt.rb ├── spec ├── spec_helper.rb └── devise-scrypt_spec.rb ├── .gitignore ├── Guardfile ├── .travis.yml ├── Gemfile ├── devise-scrypt.gemspec ├── LICENSE.txt └── README.md /.rspec: -------------------------------------------------------------------------------- 1 | --color 2 | --format documentation -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require "bundler/gem_tasks" 2 | -------------------------------------------------------------------------------- /.yardopts: -------------------------------------------------------------------------------- 1 | --markup markdown --readme README.md --title "Devise::Encryptable::Encryptors::Scrypt" -------------------------------------------------------------------------------- /lib/devise-scrypt.rb: -------------------------------------------------------------------------------- 1 | require 'devise' 2 | require 'devise-encryptable' 3 | require "devise/encryptable/encryptors/scrypt/version" 4 | require "devise/encryptable/encryptors/scrypt" -------------------------------------------------------------------------------- /lib/devise/encryptable/encryptors/scrypt/version.rb: -------------------------------------------------------------------------------- 1 | module Devise 2 | module Encryptable 3 | module Encryptors 4 | SCRYPT_VERSION = '1.0.0' 5 | end 6 | end 7 | end -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require 'rubygems' 2 | require 'simplecov' 3 | SimpleCov.start 4 | require 'bundler/setup' 5 | require 'devise-scrypt' 6 | 7 | RSpec.configure do |config| 8 | end -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | .bundle 4 | .config 5 | .yardoc 6 | Gemfile.lock 7 | InstalledFiles 8 | _yardoc 9 | coverage 10 | doc/ 11 | lib/bundler/man 12 | pkg 13 | rdoc 14 | spec/reports 15 | test/tmp 16 | test/version_tmp 17 | tmp 18 | -------------------------------------------------------------------------------- /Guardfile: -------------------------------------------------------------------------------- 1 | # A sample Guardfile 2 | # More info at https://github.com/guard/guard#readme 3 | 4 | guard 'bundler' do 5 | watch('Gemfile') 6 | watch(/^.+\.gemspec/) 7 | end 8 | 9 | guard 'rspec', :version => 2 do 10 | # Anything changes, run all specs! 11 | watch(%r{^.+\.rb$}) { 'spec' } 12 | end 13 | 14 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | script: 2 | - bundle 3 | - bundle exec rspec 4 | rvm: 5 | - ree 6 | - 1.8.7 7 | - 1.9.2 8 | - 1.9.3 9 | - ruby-head 10 | - rbx-18mode 11 | - rbx-19mode 12 | matrix: 13 | allow_failures: 14 | - rvm: ruby-head 15 | notifications: 16 | email: 17 | on_success: always 18 | on_failure: always -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Specify your gem's dependencies in gvoe_auth-client.gemspec 4 | gemspec 5 | 6 | gem 'rspec', '>= 2.11.0' 7 | gem 'simplecov' 8 | 9 | gem 'yard' 10 | 11 | gem 'guard-rspec' 12 | gem 'guard-bundler' 13 | # FS Event watching libraries for guard 14 | # inotify for Linux 15 | gem 'rb-inotify', :require => false 16 | # rb-fsevent for OS X 17 | gem 'rb-fsevent', '~> 0.9.1', :require => false -------------------------------------------------------------------------------- /devise-scrypt.gemspec: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | lib = File.expand_path('../lib', __FILE__) 3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 4 | require "devise/encryptable/encryptors/scrypt/version" 5 | 6 | Gem::Specification.new do |gem| 7 | gem.name = "devise-scrypt" 8 | gem.version = Devise::Encryptable::Encryptors::SCRYPT_VERSION 9 | gem.authors = ["Christoph Olszowka"] 10 | gem.email = ["christoph at olszowka de"] 11 | gem.description = %q{A devise-encryptable password encryptor that uses SCrypt} 12 | gem.summary = %q{A devise-encryptable password encryptor that uses SCrypt} 13 | gem.homepage = "https://github.com/capita/devise-scrypt" 14 | 15 | gem.files = `git ls-files`.split($/) 16 | gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) } 17 | gem.test_files = gem.files.grep(%r{^(test|spec|features)/}) 18 | gem.require_paths = ["lib"] 19 | 20 | gem.add_dependency 'devise', '>= 2.1.0' 21 | gem.add_dependency 'devise-encryptable', '>= 0.1.1' 22 | gem.add_dependency 'scrypt', '>= 1.1.0' 23 | end 24 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Christoph Olszowka, Capita Unternehmensberatung GmbH 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /lib/devise/encryptable/encryptors/scrypt.rb: -------------------------------------------------------------------------------- 1 | require 'scrypt' 2 | 3 | module Devise 4 | module Encryptable 5 | module Encryptors 6 | # 7 | # An encryptor for Devise passwords that uses the SCrypt algorithm. 8 | # You will need the devise-encryptable gem. Then you can switch to 9 | # scrypt by setting `config.encryptor = :scrypt` in your devise config. 10 | # 11 | # Stretches are ignored as SCrypt has different concepts for increasing 12 | # calculation complexity. 13 | # 14 | # As this uses the `scrypt` ruby gem you can configure the complexity 15 | # by setting defaults there, like so: 16 | # 17 | # SCrypt::Engine::DEFAULTS[:key_len] = 128 18 | # SCrypt::Engine::DEFAULTS[:salt_size] = 64 19 | # 20 | # Find out more about SCrypt here: 21 | # 22 | # * https://github.com/pbhogan/scrypt 23 | # * http://www.tarsnap.com/scrypt.html 24 | # 25 | class Scrypt < Base 26 | def self.digest(password, stretches, salt, pepper) 27 | SCrypt::Password.create("#{password}#{salt}#{pepper}").to_s 28 | end 29 | 30 | def self.compare(encrypted_password, password, stretches, salt, pepper) 31 | SCrypt::Password.new(encrypted_password) == "#{password}#{salt}#{pepper}" 32 | end 33 | end 34 | end 35 | end 36 | end -------------------------------------------------------------------------------- /spec/devise-scrypt_spec.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | require 'spec_helper' 3 | 4 | describe Devise::Encryptable::Encryptors::Scrypt do 5 | let(:scrypt) { Devise::Encryptable::Encryptors::Scrypt } 6 | let(:salt) { 'Salt gathered from the Dead Sea makes an excellent body scrub because of its high mineral content.' } 7 | let(:pepper) { 'A Brazilian soccer player is pepper-sprayed after refusing to leave the pitch following a red card.' } 8 | let(:password) { 'very!secret' } 9 | let(:stretches) { 10 } 10 | 11 | describe ".digest" do 12 | let(:digest) { scrypt.digest(password, stretches, salt, pepper) } 13 | 14 | it "builds a scrypt password hash" do 15 | expect(SCrypt::Password.new(digest)).to be == "#{password}#{salt}#{pepper}" 16 | end 17 | end 18 | 19 | describe ".compare" do 20 | let(:encrypted) { SCrypt::Password.create("#{password}#{salt}#{pepper}").to_s } 21 | 22 | it "is true when comparing an encrypted password against given plaintext" do 23 | expect(scrypt.compare(encrypted, password, stretches, salt, pepper)).to be_true 24 | end 25 | 26 | it "is false when comparing with wrong password" do 27 | expect(scrypt.compare(encrypted, 'foobar', stretches, salt, pepper)).to be_false 28 | end 29 | 30 | it "is false when comparing with correct password but wrong salt" do 31 | expect(scrypt.compare(encrypted, password, stretches, 'nope', pepper)).to be_false 32 | end 33 | 34 | it "is false when comparing with correct password but wrong pepper" do 35 | expect(scrypt.compare(encrypted, password, stretches, salt, 'nope')).to be_false 36 | end 37 | end 38 | 39 | end -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | devise-scrypt [![Build Status](https://secure.travis-ci.org/capita/devise-scrypt.png)][Continuous Integration] 2 | ============= 3 | 4 | **A [devise-encryptable] password encryptor that uses [SCrypt]** 5 | 6 | * [Source Code] 7 | * [API documentation] 8 | * [Rubygem] 9 | * [Continuous Integration] 10 | 11 | [Source Code]: https://github.com/capita/devise-scrypt "Source Code @ GitHub" 12 | [API documentation]: http://rubydoc.info/gems/devise-scrypt/frames "API Documentation at Rubydoc.info" 13 | [Rubygem]: http://rubygems.org/gems/devise-scrypt "Rubygem @ rubygems.org" 14 | [Continuous Integration]: http://travis-ci.org/capita/devise-scrypt "Continuous integration @ travis-ci.org" 15 | 16 | [SCrypt]: https://github.com/pbhogan/scrypt "scrypt rubygem" 17 | [devise]: https://github.com/plataformatec/devise "devise rubygem" 18 | [devise-encryptable]: https://github.com/plataformatec/devise-encryptable "devise-encryptable plugin" 19 | 20 | 21 | ## Usage 22 | 23 | Assuming you have [devise] (>= 2.1) and the [devise-encryptable] plugin 24 | set up in your application, add `devise-scrypt` to your `Gemfile` and `bundle`: 25 | 26 | gem 'devise-scrypt' 27 | 28 | Then open up your [devise] configuration, which supposedly lives at 29 | `config/initializers/devise.rb` and configure your encryptor to be `scrypt`: 30 | 31 | # config/initializers/devise.rb 32 | Devise.setup do |config| 33 | # .. 34 | config.encryptor = :scrypt 35 | # ... 36 | end 37 | 38 | It is also recommended to uncomment (or add) `config.pepper` with a random 39 | string that will be used in addition to the per-user `password_salt` when hashing. 40 | 41 | ## Configuring algorithm complexity 42 | 43 | The `config.stretches` option does not affect the calculation complexity. Instead, 44 | please adjust the `scrypt` defaults to your liking. Please note that in the test 45 | environment you will probably want to reduce complexity if you find your test suite 46 | slows down significantly. Please refer to the [SCrypt] gem documentation about SCrypt 47 | config options and their effect. 48 | 49 | # Example config: 50 | SCrypt::Engine::DEFAULTS[:key_len] = 64 51 | SCrypt::Engine::DEFAULTS[:salt_size] = 32 52 | 53 | ## [Compatibility][Continuous Integration] 54 | 55 | The [test suite passes against][Continuous Integration] MRI 1.8.7, 1.9.2, 1.9.3, REE, 56 | and Rubinius in both 1.8 and 1.9 modes. 57 | 58 | JRuby is not supported because the [SCrypt] gem is a C extension and therefore is 59 | incompatible with it. 60 | 61 | ## Contributing 62 | 63 | 1. Fork it 64 | 2. Create your feature branch (`git checkout -b my-new-feature`) 65 | 3. Commit your changes (`git commit -am 'Add some feature'`) 66 | 4. Push to the branch (`git push origin my-new-feature`) 67 | 5. Create new Pull Request 68 | 69 | ## Copyright 70 | 71 | Copyright (c) 2012 Christoph Olszowka, Capita Unternehmensberatung GmbH 72 | 73 | Released under MIT License. See `LICENSE.txt` --------------------------------------------------------------------------------