scrypt 3.0.6 → 3.0.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SCrypt
4
+ module Errors
5
+ # The salt parameter provided is invalid.
6
+ class InvalidSalt < StandardError; end
7
+
8
+ # The hash parameter provided is invalid.
9
+ class InvalidHash < StandardError; end
10
+
11
+ # The secret parameter provided is invalid.
12
+ class InvalidSecret < StandardError; end
13
+ end
14
+ end
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SCrypt
4
+ # A password management class which allows you to safely store users' passwords and compare them.
5
+ #
6
+ # Example usage:
7
+ #
8
+ # include "scrypt"
9
+ #
10
+ # # hash a user's password
11
+ # @password = Password.create("my grand secret")
12
+ # @password #=> "2000$8$1$f5f2fa5fe5484a7091f1299768fbe92b5a7fbc77$6a385f22c54d92c314b71a4fd5ef33967c93d679"
13
+ #
14
+ # # store it safely
15
+ # @user.update_attribute(:password, @password)
16
+ #
17
+ # # read it back
18
+ # @user.reload!
19
+ # @db_password = Password.new(@user.password)
20
+ #
21
+ # # compare it after retrieval
22
+ # @db_password == "my grand secret" #=> true
23
+ # @db_password == "a paltry guess" #=> false
24
+ #
25
+ class Password < String
26
+ # The hash portion of the stored password hash.
27
+ attr_reader :digest
28
+ # The salt of the store password hash
29
+ attr_reader :salt
30
+ # The cost factor used to create the hash.
31
+ attr_reader :cost
32
+
33
+ class << self
34
+ # Hashes a secret, returning a SCrypt::Password instance.
35
+ # Takes five options (optional), which will determine the salt/key's length and the cost limits of the computation.
36
+ # <tt>:key_len</tt> specifies the length in bytes of the key you want to generate. The default is 32 bytes (256 bits). Minimum is 16 bytes (128 bits). Maximum is 512 bytes (4096 bits).
37
+ # <tt>:salt_size</tt> specifies the size in bytes of the random salt you want to generate. The default and minimum is 8 bytes (64 bits). Maximum is 32 bytes (256 bits).
38
+ # <tt>:max_time</tt> specifies the maximum number of seconds the computation should take.
39
+ # <tt>:max_mem</tt> specifies the maximum number of bytes the computation should take. A value of 0 specifies no upper limit. The minimum is always 1 MB.
40
+ # <tt>:max_memfrac</tt> specifies the maximum memory in a fraction of available resources to use. Any value equal to 0 or greater than 0.5 will result in 0.5 being used.
41
+ # The scrypt key derivation function is designed to be far more secure against hardware brute-force attacks than alternative functions such as PBKDF2 or bcrypt.
42
+ # The designers of scrypt estimate that on modern (2009) hardware, if 5 seconds are spent computing a derived key, the cost of a hardware brute-force attack against scrypt is roughly 4000 times greater than the cost of a similar attack against bcrypt (to find the same password), and 20000 times greater than a similar attack against PBKDF2.
43
+ # Default options will result in calculation time of approx. 200 ms with 1 MB memory use.
44
+ #
45
+ # Example:
46
+ # @password = SCrypt::Password.create("my secret", :max_time => 0.25)
47
+ #
48
+ def create(secret, options = {})
49
+ options = SCrypt::Engine::DEFAULTS.merge(options)
50
+
51
+ # Clamp minimum/maximum keylen
52
+ options[:key_len] = 16 if options[:key_len] < 16
53
+ options[:key_len] = 512 if options[:key_len] > 512
54
+
55
+ # Clamp minimum/maximum salt_size
56
+ options[:salt_size] = 8 if options[:salt_size] < 8
57
+ options[:salt_size] = 32 if options[:salt_size] > 32
58
+
59
+ salt = SCrypt::Engine.generate_salt(options)
60
+ hash = SCrypt::Engine.hash_secret(secret, salt, options[:key_len])
61
+
62
+ Password.new(hash)
63
+ end
64
+ end
65
+
66
+ # Initializes a SCrypt::Password instance with the data from a stored hash.
67
+ def initialize(raw_hash)
68
+ raise Errors::InvalidHash, 'invalid hash' unless valid_hash?(raw_hash)
69
+
70
+ replace(raw_hash)
71
+
72
+ @cost, @salt, @digest = split_hash(to_s)
73
+ end
74
+
75
+ # Compares a potential secret against the hash. Returns true if the secret is the original secret, false otherwise.
76
+ def ==(other)
77
+ SecurityUtils.secure_compare(self, SCrypt::Engine.hash_secret(other, @cost + @salt, digest.length / 2))
78
+ end
79
+ alias is_password? ==
80
+
81
+ private
82
+
83
+ # Returns true if +h+ is a valid hash.
84
+ def valid_hash?(h)
85
+ h.match(/^[0-9a-z]+\$[0-9a-z]+\$[0-9a-z]+\$[A-Za-z0-9]{16,64}\$[A-Za-z0-9]{32,1024}$/) != nil
86
+ end
87
+
88
+ # call-seq:
89
+ # split_hash(raw_hash) -> cost, salt, hash
90
+ #
91
+ # Splits +h+ into cost, salt, and hash and returns them in that order.
92
+ def split_hash(h)
93
+ n, v, r, salt, hash = h.split('$')
94
+ [[n, v, r].join('$') + '$', salt, hash]
95
+ end
96
+ end
97
+ end
@@ -1,9 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'ffi'
2
4
  require 'ffi-compiler/loader'
3
5
 
4
6
  module SCrypt
5
7
  module Ext
6
8
  extend FFI::Library
9
+
7
10
  ffi_lib FFI::Compiler::Loader.find('scrypt_ext')
8
11
  end
9
12
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # NOTE:: a verbatim copy of https://github.com/rails/rails/blob/c8c660002f4b0e9606de96325f20b95248b6ff2d/activesupport/lib/active_support/security_utils.rb
2
4
  # Please see the Rails license: https://github.com/rails/rails/blob/master/activesupport/MIT-LICENSE
3
5
 
@@ -9,15 +11,14 @@ module SCrypt
9
11
  # that have already been processed by HMAC. This should not be used
10
12
  # on variable length plaintext strings because it could leak length info
11
13
  # via timing attacks.
12
- def secure_compare(a, b)
14
+ def self.secure_compare(a, b)
13
15
  return false unless a.bytesize == b.bytesize
14
16
 
15
17
  l = a.unpack "C#{a.bytesize}"
16
18
 
17
19
  res = 0
18
20
  b.each_byte { |byte| res |= byte ^ l.shift }
19
- res == 0
21
+ res.zero?
20
22
  end
21
- module_function :secure_compare
22
23
  end
23
24
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SCrypt
2
- VERSION = "3.0.6"
4
+ VERSION = '3.0.7'
3
5
  end
@@ -1,37 +1,55 @@
1
- # -*- encoding: utf-8 -*-
1
+ # frozen_string_literal: true
2
+
3
+ # rubocop:disable Performance/EndWith, Style/SpecialGlobalVars
4
+
2
5
  $:.push File.expand_path("../lib", __FILE__)
3
- require "scrypt/version"
6
+ require 'scrypt/version'
4
7
 
5
8
  Gem::Specification.new do |s|
6
- s.name = "scrypt"
9
+ s.name = 'scrypt'
7
10
  s.version = SCrypt::VERSION
8
- s.authors = ["Patrick Hogan", "Stephen von Takach", "Rene van Paassen" ]
9
- s.email = ["pbhogan@gmail.com", "steve@advancedcontrol.com.au",
10
- "rene.vanpaassen@gmail.com" ]
11
- s.cert_chain = ['certs/pbhogan.pem']
11
+ s.authors = ['Patrick Hogan',
12
+ 'Stephen von Takach',
13
+ 'Rene van Paassen',
14
+ 'Johanns Gregorian']
15
+ s.email = ['pbhogan@gmail.com',
16
+ 'steve@advancedcontrol.com.au',
17
+ 'rene.vanpaassen@gmail.com',
18
+ 'io+scrypt@jsg.io']
19
+ s.cert_chain = ['certs/stakach.pem']
12
20
  s.license = 'BSD-3-Clause'
13
- s.signing_key = File.expand_path("~/.ssh/gem-private_key.pem") if $0 =~ /gem\z/
14
- s.homepage = "https://github.com/pbhogan/scrypt"
15
- s.summary = "scrypt password hashing algorithm."
16
- s.description = <<-EOF
21
+
22
+ s.signing_key = File.expand_path('~/.ssh/gem-private_key.pem') if $0 =~ /gem\z/
23
+
24
+ s.homepage = 'https://github.com/pbhogan/scrypt'
25
+ s.summary = 'scrypt password hashing algorithm.'
26
+
27
+ s.description = <<-DESC
17
28
  The scrypt key derivation function is designed to be far
18
29
  more secure against hardware brute-force attacks than
19
30
  alternative functions such as PBKDF2 or bcrypt.
20
- EOF
31
+ DESC
21
32
 
22
33
  s.add_dependency 'ffi-compiler', '>= 1.0', '< 2.0'
34
+ s.add_development_dependency 'awesome_print', '>= 1', '< 2'
23
35
  s.add_development_dependency 'rake', '>= 9', '< 13'
24
- s.add_development_dependency 'rspec', '>= 3', '< 4'
25
36
  s.add_development_dependency 'rdoc', '>= 4', '< 5'
26
- s.add_development_dependency 'awesome_print', '>= 1', '< 2'
37
+ s.add_development_dependency 'rspec', '>= 3', '< 4'
38
+
39
+ if RUBY_VERSION >= '2.5'
40
+ s.add_development_dependency 'rubocop', '>= 0.76.0', '< 1.0.0'
41
+ s.add_development_dependency 'rubocop-gitlab-security', '>= 0.1.1', '< 0.2'
42
+ s.add_development_dependency 'rubocop-performance', '>= 1.5.0', '< 1.6.0'
43
+ end
27
44
 
28
- s.rubyforge_project = "scrypt"
45
+ s.rubyforge_project = 'scrypt'
29
46
 
30
- s.extensions = ["ext/scrypt/Rakefile"]
47
+ s.extensions = ['ext/scrypt/Rakefile']
31
48
 
32
- s.files = %w(Rakefile scrypt.gemspec README.md COPYING) + Dir.glob("{lib,spec,autotest}/**/*")
33
- s.files += Dir.glob("ext/scrypt/*")
34
- s.test_files = Dir.glob("spec/**/*")
35
- s.require_paths = ["lib"]
49
+ s.files = %w[Rakefile scrypt.gemspec README.md COPYING] + Dir.glob('{lib,spec,autotest}/**/*')
50
+ s.files += Dir.glob('ext/scrypt/*')
51
+ s.test_files = Dir.glob('spec/**/*')
52
+ s.require_paths = ['lib']
36
53
  end
37
54
 
55
+ # rubocop:enable
@@ -1,84 +1,81 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), "..", "spec_helper"))
1
+ # frozen_string_literal: true
2
2
 
3
- describe "The SCrypt engine" do
4
- it "should calculate a valid cost factor" do
5
- first = SCrypt::Engine.calibrate(:max_time => 0.2)
3
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
4
+
5
+ describe 'The SCrypt engine' do
6
+ it 'should calculate a valid cost factor' do
7
+ first = SCrypt::Engine.calibrate(max_time: 0.2)
6
8
  expect(SCrypt::Engine.valid_cost?(first)).to equal(true)
7
9
  end
8
10
  end
9
11
 
10
-
11
- describe "Generating SCrypt salts" do
12
- it "should produce strings" do
12
+ describe 'Generating SCrypt salts' do
13
+ it 'should produce strings' do
13
14
  expect(SCrypt::Engine.generate_salt).to be_an_instance_of(String)
14
15
  end
15
16
 
16
- it "should produce random data" do
17
+ it 'should produce random data' do
17
18
  expect(SCrypt::Engine.generate_salt).not_to equal(SCrypt::Engine.generate_salt)
18
19
  end
19
20
 
20
- it "should used the saved cost factor" do
21
+ it 'should used the saved cost factor' do
21
22
  # Verify cost is different before saving
22
- cost = SCrypt::Engine.calibrate(:max_time => 0.01)
23
- expect(SCrypt::Engine.generate_salt(:max_time => 30, :max_mem => 64*1024*1024)).not_to start_with(cost)
23
+ cost = SCrypt::Engine.calibrate(max_time: 0.01)
24
+ expect(SCrypt::Engine.generate_salt(max_time: 30, max_mem: 64 * 1024 * 1024)).not_to start_with(cost)
24
25
 
25
- cost = SCrypt::Engine.calibrate!(:max_time => 0.01)
26
- expect(SCrypt::Engine.generate_salt(:max_time => 30, :max_mem => 64*1024*1024)).to start_with(cost)
26
+ cost = SCrypt::Engine.calibrate!(max_time: 0.01)
27
+ expect(SCrypt::Engine.generate_salt(max_time: 30, max_mem: 64 * 1024 * 1024)).to start_with(cost)
27
28
  end
28
29
  end
29
30
 
30
-
31
- describe "Autodetecting of salt cost" do
32
- it "should work" do
33
- expect(SCrypt::Engine.autodetect_cost("2a$08$c3$randomjunkgoeshere")).to eq("2a$08$c3$")
31
+ describe 'Autodetecting of salt cost' do
32
+ it 'should work' do
33
+ expect(SCrypt::Engine.autodetect_cost('2a$08$c3$randomjunkgoeshere')).to eq('2a$08$c3$')
34
34
  end
35
35
  end
36
36
 
37
-
38
- describe "Generating SCrypt hashes" do
39
-
37
+ describe 'Generating SCrypt hashes' do
40
38
  class MyInvalidSecret
41
39
  undef to_s
42
40
  end
43
41
 
44
42
  before :each do
45
43
  @salt = SCrypt::Engine.generate_salt
46
- @password = "woo"
44
+ @password = 'woo'
47
45
  end
48
46
 
49
- it "should produce a string" do
47
+ it 'should produce a string' do
50
48
  expect(SCrypt::Engine.hash_secret(@password, @salt)).to be_an_instance_of(String)
51
49
  end
52
50
 
53
- it "should raise an InvalidSalt error if the salt is invalid" do
54
- expect(lambda { SCrypt::Engine.hash_secret(@password, 'nino') }).to raise_error(SCrypt::Errors::InvalidSalt)
51
+ it 'should raise an InvalidSalt error if the salt is invalid' do
52
+ expect(-> { SCrypt::Engine.hash_secret(@password, 'nino') }).to raise_error(SCrypt::Errors::InvalidSalt)
55
53
  end
56
54
 
57
- it "should raise an InvalidSecret error if the secret is invalid" do
58
- expect(lambda { SCrypt::Engine.hash_secret(MyInvalidSecret.new, @salt) }).to raise_error(SCrypt::Errors::InvalidSecret)
59
- expect(lambda { SCrypt::Engine.hash_secret(nil, @salt) }).to_not raise_error
60
- expect(lambda { SCrypt::Engine.hash_secret(false, @salt) }).to_not raise_error
55
+ it 'should raise an InvalidSecret error if the secret is invalid' do
56
+ expect(-> { SCrypt::Engine.hash_secret(MyInvalidSecret.new, @salt) }).to raise_error(SCrypt::Errors::InvalidSecret)
57
+ expect(-> { SCrypt::Engine.hash_secret(nil, @salt) }).to_not raise_error
58
+ expect(-> { SCrypt::Engine.hash_secret(false, @salt) }).to_not raise_error
61
59
  end
62
60
 
63
- it "should call #to_s on the secret and use the return value as the actual secret data" do
64
- expect(SCrypt::Engine.hash_secret(false, @salt)).to eq(SCrypt::Engine.hash_secret("false", @salt))
61
+ it 'should call #to_s on the secret and use the return value as the actual secret data' do
62
+ expect(SCrypt::Engine.hash_secret(false, @salt)).to eq(SCrypt::Engine.hash_secret('false', @salt))
65
63
  end
66
64
  end
67
65
 
68
- describe "SCrypt test vectors" do
69
- it "should match results of SCrypt function" do
70
-
66
+ describe 'SCrypt test vectors' do
67
+ it 'should match results of SCrypt function' do
71
68
  expect(SCrypt::Engine.scrypt('', '', 16, 1, 1, 64).unpack('H*').first).to eq('77d6576238657b203b19ca42c18a0497f16b4844e3074ae8dfdffa3fede21442fcd0069ded0948f8326a753a0fc81f17e8d3e0fb2e0d3628cf35e20c38d18906')
72
69
  expect(SCrypt::Engine.scrypt('password', 'NaCl', 1024, 8, 16, 64).unpack('H*').first).to eq('fdbabe1c9d3472007856e7190d01e9fe7c6ad7cbc8237830e77376634b3731622eaf30d92e22a3886ff109279d9830dac727afb94a83ee6d8360cbdfa2cc0640')
73
- expect(SCrypt::Engine.scrypt('pleaseletmein', 'SodiumChloride', 16384, 8, 1, 64).unpack('H*').first).to eq('7023bdcb3afd7348461c06cd81fd38ebfda8fbba904f8e3ea9b543f6545da1f2d5432955613f0fcf62d49705242a9af9e61e85dc0d651e40dfcf017b45575887')
70
+ expect(SCrypt::Engine.scrypt('pleaseletmein', 'SodiumChloride', 16_384, 8, 1, 64).unpack('H*').first).to eq('7023bdcb3afd7348461c06cd81fd38ebfda8fbba904f8e3ea9b543f6545da1f2d5432955613f0fcf62d49705242a9af9e61e85dc0d651e40dfcf017b45575887')
74
71
  # Raspberry is memory limited, and fails on this test
75
- # expect(SCrypt::Engine.scrypt('pleaseletmein', 'SodiumChloride', 1048576, 8, 1, 64).unpack('H*').first).to eq('2101cb9b6a511aaeaddbbe09cf70f881ec568d574a2ffd4dabe5ee9820adaa478e56fd8f4ba5d09ffa1c6d927c40f4c337304049e8a952fbcbf45c6fa77a41a4')
72
+ # expect(SCrypt::Engine.scrypt('pleaseletmein', 'SodiumChloride', 1048576, 8, 1, 64).unpack('H*').first).to eq('2101cb9b6a511aaeaddbbe09cf70f881ec568d574a2ffd4dabe5ee9820adaa478e56fd8f4ba5d09ffa1c6d927c40f4c337304049e8a952fbcbf45c6fa77a41a4')
76
73
  end
77
74
 
78
- it "should match equivalent results sent through hash_secret() function" do
75
+ it 'should match equivalent results sent through hash_secret() function' do
79
76
  expect(SCrypt::Engine.hash_secret('', '10$1$1$0000000000000000', 64)).to match(/\$77d6576238657b203b19ca42c18a0497f16b4844e3074ae8dfdffa3fede21442fcd0069ded0948f8326a753a0fc81f17e8d3e0fb2e0d3628cf35e20c38d18906$/)
80
77
  expect(SCrypt::Engine.hash_secret('password', '400$8$10$000000004e61436c', 64)).to match(/\$fdbabe1c9d3472007856e7190d01e9fe7c6ad7cbc8237830e77376634b3731622eaf30d92e22a3886ff109279d9830dac727afb94a83ee6d8360cbdfa2cc0640$/)
81
78
  expect(SCrypt::Engine.hash_secret('pleaseletmein', '4000$8$1$536f6469756d43686c6f72696465', 64)).to match(/\$7023bdcb3afd7348461c06cd81fd38ebfda8fbba904f8e3ea9b543f6545da1f2d5432955613f0fcf62d49705242a9af9e61e85dc0d651e40dfcf017b45575887$/)
82
- # expect(SCrypt::Engine.hash_secret('pleaseletmein', '100000$8$1$536f6469756d43686c6f72696465', 64)).to match(/\$2101cb9b6a511aaeaddbbe09cf70f881ec568d574a2ffd4dabe5ee9820adaa478e56fd8f4ba5d09ffa1c6d927c40f4c337304049e8a952fbcbf45c6fa77a41a4$/)
79
+ # expect(SCrypt::Engine.hash_secret('pleaseletmein', '100000$8$1$536f6469756d43686c6f72696465', 64)).to match(/\$2101cb9b6a511aaeaddbbe09cf70f881ec568d574a2ffd4dabe5ee9820adaa478e56fd8f4ba5d09ffa1c6d927c40f4c337304049e8a952fbcbf45c6fa77a41a4$/)
83
80
  end
84
81
  end
@@ -1,137 +1,135 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), "..", "spec_helper"))
1
+ # frozen_string_literal: true
2
2
 
3
- describe "Creating a hashed password" do
3
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
4
+
5
+ describe 'Creating a hashed password' do
4
6
  before :each do
5
- @password = SCrypt::Password.create("s3cr3t", :max_time => 0.25)
7
+ @password = SCrypt::Password.create('s3cr3t', max_time: 0.25)
6
8
  end
7
9
 
8
- it "should return a SCrypt::Password" do
10
+ it 'should return a SCrypt::Password' do
9
11
  expect(@password).to be_an_instance_of(SCrypt::Password)
10
12
  end
11
13
 
12
- it "should return a valid password" do
13
- expect(lambda { SCrypt::Password.new(@password) }).to_not raise_error
14
+ it 'should return a valid password' do
15
+ expect(-> { SCrypt::Password.new(@password) }).to_not raise_error
14
16
  end
15
17
 
16
- it "should behave normally if the secret is not a string" do
17
- expect(lambda { SCrypt::Password.create(nil) }).to_not raise_error
18
- expect(lambda { SCrypt::Password.create({:woo => "yeah"}) }).to_not raise_error
19
- expect(lambda { SCrypt::Password.create(false) }).to_not raise_error
18
+ it 'should behave normally if the secret is not a string' do
19
+ expect(-> { SCrypt::Password.create(nil) }).to_not raise_error
20
+ expect(-> { SCrypt::Password.create(woo: 'yeah') }).to_not raise_error
21
+ expect(-> { SCrypt::Password.create(false) }).to_not raise_error
20
22
  end
21
23
 
22
- it "should tolerate empty string secrets" do
23
- expect(lambda { SCrypt::Password.create( "\n".chop ) }).to_not raise_error
24
- expect(lambda { SCrypt::Password.create( "" ) }).to_not raise_error
25
- expect(lambda { SCrypt::Password.create( String.new ) }).to_not raise_error
24
+ it 'should tolerate empty string secrets' do
25
+ expect(-> { SCrypt::Password.create("\n".chop) }).to_not raise_error
26
+ expect(-> { SCrypt::Password.create('') }).to_not raise_error
27
+ expect(-> { SCrypt::Password.create('') }).to_not raise_error
26
28
  end
27
29
  end
28
30
 
29
-
30
- describe "Reading a hashed password" do
31
+ describe 'Reading a hashed password' do
31
32
  before :each do
32
- @secret = "my secret"
33
- @hash = "400$8$d$173a8189751c095a29b933789560b73bf17b2e01$9bf66d74bd6f3ebcf99da3b379b689b89db1cb07"
33
+ @secret = 'my secret'
34
+ @hash = '400$8$d$173a8189751c095a29b933789560b73bf17b2e01$9bf66d74bd6f3ebcf99da3b379b689b89db1cb07'
34
35
  end
35
36
 
36
- it "should read the cost, salt, and hash" do
37
+ it 'should read the cost, salt, and hash' do
37
38
  password = SCrypt::Password.new(@hash)
38
- expect(password.cost).to eq("400$8$d$")
39
- expect(password.salt).to eq("173a8189751c095a29b933789560b73bf17b2e01")
39
+ expect(password.cost).to eq('400$8$d$')
40
+ expect(password.salt).to eq('173a8189751c095a29b933789560b73bf17b2e01')
40
41
  expect(password.to_s).to eq(@hash)
41
42
  end
42
43
 
43
- it "should raise an InvalidHashError when given an invalid hash" do
44
- expect(lambda { SCrypt::Password.new('not a valid hash') }).to raise_error(SCrypt::Errors::InvalidHash)
44
+ it 'should raise an InvalidHashError when given an invalid hash' do
45
+ expect(-> { SCrypt::Password.new('not a valid hash') }).to raise_error(SCrypt::Errors::InvalidHash)
45
46
  end
46
47
  end
47
48
 
48
- describe "Comparing a hashed password with a secret" do
49
+ describe 'Comparing a hashed password with a secret' do
49
50
  before :each do
50
- @secret = "s3cr3t"
51
+ @secret = 's3cr3t'
51
52
  @password = SCrypt::Password.create(@secret)
52
53
  end
53
54
 
54
- it "should compare successfully to the original secret" do
55
+ it 'should compare successfully to the original secret' do
55
56
  expect((@password == @secret)).to be(true)
56
57
  end
57
58
 
58
- it "should compare unsuccessfully to anything besides original secret" do
59
- expect((@password == "@secret")).to be(false)
59
+ it 'should compare unsuccessfully to anything besides original secret' do
60
+ expect((@password == '@secret')).to be(false)
60
61
  end
61
-
62
62
  end
63
63
 
64
- describe "non-default salt sizes" do
64
+ describe 'non-default salt sizes' do
65
65
  before :each do
66
- @secret = "s3cret"
66
+ @secret = 's3cret'
67
67
  end
68
68
 
69
- it "should enforce a minimum salt of 8 bytes" do
70
- @password = SCrypt::Password.create(@secret, :salt_size => 7)
69
+ it 'should enforce a minimum salt of 8 bytes' do
70
+ @password = SCrypt::Password.create(@secret, salt_size: 7)
71
71
  expect(@password.salt.length).to eq(8 * 2)
72
72
  end
73
73
 
74
- it "should allow a salt of 32 bytes" do
75
- @password = SCrypt::Password.create(@secret, :salt_size => 32)
74
+ it 'should allow a salt of 32 bytes' do
75
+ @password = SCrypt::Password.create(@secret, salt_size: 32)
76
76
  expect(@password.salt.length).to eq(32 * 2)
77
77
  end
78
78
 
79
- it "should enforce a maximum salt of 32 bytes" do
80
- @password = SCrypt::Password.create(@secret, :salt_size => 33)
79
+ it 'should enforce a maximum salt of 32 bytes' do
80
+ @password = SCrypt::Password.create(@secret, salt_size: 33)
81
81
  expect(@password.salt.length).to eq(32 * 2)
82
82
  end
83
83
 
84
- it "should pad a 20-byte salt to not look like a 20-byte SHA1" do
85
- @password = SCrypt::Password.create(@secret, :salt_size => 20)
84
+ it 'should pad a 20-byte salt to not look like a 20-byte SHA1' do
85
+ @password = SCrypt::Password.create(@secret, salt_size: 20)
86
86
  expect(@password.salt.length).to eq(41)
87
87
  end
88
88
 
89
- it "should properly compare a non-standard salt hash" do
90
- @password = SCrypt::Password.create(@secret, :salt_size => 20)
89
+ it 'should properly compare a non-standard salt hash' do
90
+ @password = SCrypt::Password.create(@secret, salt_size: 20)
91
91
  expect((SCrypt::Password.new(@password.to_s) == @secret)).to be(true)
92
92
  end
93
-
94
93
  end
95
94
 
96
- describe "non-default key lengths" do
95
+ describe 'non-default key lengths' do
97
96
  before :each do
98
- @secret = "s3cret"
97
+ @secret = 's3cret'
99
98
  end
100
99
 
101
- it "should enforce a minimum keylength of 16 bytes" do
102
- @password = SCrypt::Password.create(@secret, :key_len => 15)
100
+ it 'should enforce a minimum keylength of 16 bytes' do
101
+ @password = SCrypt::Password.create(@secret, key_len: 15)
103
102
  expect(@password.digest.length).to eq(16 * 2)
104
103
  end
105
104
 
106
- it "should allow a keylength of 512 bytes" do
107
- @password = SCrypt::Password.create(@secret, :key_len => 512)
105
+ it 'should allow a keylength of 512 bytes' do
106
+ @password = SCrypt::Password.create(@secret, key_len: 512)
108
107
  expect(@password.digest.length).to eq(512 * 2)
109
108
  end
110
109
 
111
- it "should enforce a maximum keylength of 512 bytes" do
112
- @password = SCrypt::Password.create(@secret, :key_len => 513)
110
+ it 'should enforce a maximum keylength of 512 bytes' do
111
+ @password = SCrypt::Password.create(@secret, key_len: 513)
113
112
  expect(@password.digest.length).to eq(512 * 2)
114
113
  end
115
114
 
116
- it "should properly compare a non-standard hash" do
117
- @password = SCrypt::Password.create(@secret, :key_len => 512)
115
+ it 'should properly compare a non-standard hash' do
116
+ @password = SCrypt::Password.create(@secret, key_len: 512)
118
117
  expect((SCrypt::Password.new(@password.to_s) == @secret)).to be(true)
119
118
  end
120
-
121
119
  end
122
120
 
123
- describe "Old-style hashes" do
121
+ describe 'Old-style hashes' do
124
122
  before :each do
125
- @secret = "my secret"
126
- @hash = "400$8$d$173a8189751c095a29b933789560b73bf17b2e01$9bf66d74bd6f3ebcf99da3b379b689b89db1cb07"
123
+ @secret = 'my secret'
124
+ @hash = '400$8$d$173a8189751c095a29b933789560b73bf17b2e01$9bf66d74bd6f3ebcf99da3b379b689b89db1cb07'
127
125
  end
128
126
 
129
- it "should compare successfully" do
127
+ it 'should compare successfully' do
130
128
  expect((SCrypt::Password.new(@hash) == @secret)).to be(true)
131
129
  end
132
130
  end
133
131
 
134
- describe "Respecting standard ruby behaviors" do
132
+ describe 'Respecting standard ruby behaviors' do
135
133
  it 'should hash as an integer' do
136
134
  password = SCrypt::Password.create('')
137
135
  expect(password.hash).to be_kind_of(Integer)