File: password_spec.rb

package info (click to toggle)
ruby-bcrypt 3.1.20-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 340 kB
  • sloc: ansic: 1,390; java: 764; ruby: 438; asm: 157; makefile: 12
file content (137 lines) | stat: -rw-r--r-- 4,935 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
require File.expand_path(File.join(File.dirname(__FILE__), "..", "spec_helper"))
require 'securerandom'

describe "Creating a hashed password" do

  before :each do
    @secret = "wheedle"
    @password = BCrypt::Password.create(@secret, :cost => 4)
  end

  specify "should return a BCrypt::Password" do
    expect(@password).to be_an_instance_of(BCrypt::Password)
  end

  specify "should return a valid bcrypt password" do
    expect { BCrypt::Password.new(@password) }.not_to raise_error
  end

  specify "should behave normally if the secret is not a string" do
    expect { BCrypt::Password.create(nil) }.not_to raise_error
    expect { BCrypt::Password.create({:woo => "yeah"}) }.not_to raise_error
    expect { BCrypt::Password.create(false) }.not_to raise_error
  end

  specify "should tolerate empty string secrets" do
    expect { BCrypt::Password.create( "\n".chop  ) }.not_to raise_error
    expect { BCrypt::Password.create( ""         ) }.not_to raise_error
    expect { BCrypt::Password.create( String.new ) }.not_to raise_error
  end

  specify "should tolerate very long string secrets" do
    expect { BCrypt::Password.create("abcd"*1024) }.not_to raise_error
  end

  specify "blows up when null bytes are in the string" do
    # JRuby can handle the null bytes
    skip if RUBY_ENGINE == 'jruby'
    expect { BCrypt::Password.create( "foo\0bar".chop  ) }.to raise_error
  end
end

describe "Reading a hashed password" do
  before :each do
    @secret = "U*U"
    @hash = "$2a$05$CCCCCCCCCCCCCCCCCCCCC.E5YPO9kmyuRGyh0XouQYb4YMJKvyOeW"
  end

  specify "the cost is too damn high" do
    expect {
      BCrypt::Password.create("hello", :cost => 32)
    }.to raise_error(ArgumentError)
  end

  specify "the cost should be set to the default if nil" do
    expect(BCrypt::Password.create("hello", :cost => nil).cost).to equal(BCrypt::Engine::DEFAULT_COST)
  end

  specify "the cost should be set to the default if empty hash" do
    expect(BCrypt::Password.create("hello", {}).cost).to equal(BCrypt::Engine::DEFAULT_COST)
  end

  specify "the cost should be set to the passed value if provided" do
    expect(BCrypt::Password.create("hello", :cost => 5).cost).to equal(5)
  end

  specify "the cost should be set to the global value if set" do
    BCrypt::Engine.cost = 5
    expect(BCrypt::Password.create("hello").cost).to equal(5)
    # unset the global value to not affect other tests
    BCrypt::Engine.cost = nil
  end

  specify "the cost should be set to an overridden constant for backwards compatibility" do
    # suppress "already initialized constant" warning
    old_verbose, $VERBOSE = $VERBOSE, nil
    old_default_cost = BCrypt::Engine::DEFAULT_COST

    BCrypt::Engine::DEFAULT_COST = 5
    expect(BCrypt::Password.create("hello").cost).to equal(5)

    # reset default to not affect other tests
    BCrypt::Engine::DEFAULT_COST = old_default_cost
    $VERBOSE = old_verbose
  end

  specify "should read the version, cost, salt, and hash" do
    password = BCrypt::Password.new(@hash)
    expect(password.version).to eql("2a")
    expect(password.version.class).to eq String
    expect(password.cost).to equal(5)
    expect(password.salt).to eql("$2a$05$CCCCCCCCCCCCCCCCCCCCC.")
    expect(password.salt.class).to eq String
    expect(password.checksum).to eq("E5YPO9kmyuRGyh0XouQYb4YMJKvyOeW")
    expect(password.checksum.class).to eq String
    expect(password.to_s).to eql(@hash)
  end

  specify "should raise an InvalidHashError when given an invalid hash" do
    expect { BCrypt::Password.new('weedle') }.to raise_error(BCrypt::Errors::InvalidHash)
  end
end

describe "Comparing a hashed password with a secret" do
  before :each do
    @secret = "U*U"
    @hash = "$2a$05$CCCCCCCCCCCCCCCCCCCCC.E5YPO9kmyuRGyh0XouQYb4YMJKvyOeW"
    @password = BCrypt::Password.create(@secret)
  end

  specify "should compare successfully to the original secret" do
    expect((@password == @secret)).to be(true)
  end

  specify "should compare unsuccessfully to anything besides original secret" do
    expect((@password == "@secret")).to be(false)
  end
end

describe "Validating a generated salt" do
  specify "should not accept an invalid salt" do
    expect(BCrypt::Engine.valid_salt?("invalid")).to eq(false)
    expect(BCrypt::Engine.valid_salt?("invalid\n#{BCrypt::Engine.generate_salt}\ninvalid")).to eq(false)
  end
  specify "should accept a valid salt" do
    expect(BCrypt::Engine.valid_salt?(BCrypt::Engine.generate_salt)).to eq(true)
  end
end

describe "Validating a password hash" do
  specify "should not accept an invalid password" do
    expect(BCrypt::Password.valid_hash?("i_am_so_not_valid")).to be(false)
    expect(BCrypt::Password.valid_hash?("invalid\n#{BCrypt::Password.create "i_am_so_valid"}\ninvalid")).to be(false)
  end
  specify "should accept a valid password" do
    expect(BCrypt::Password.valid_hash?(BCrypt::Password.create "i_am_so_valid")).to be(true)
  end
end