bcrypt-ruby-maglev- 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,194 @@
1
+ // Copyright (c) 2006 Damien Miller <djm@mindrot.org>
2
+ //
3
+ // Permission to use, copy, modify, and distribute this software for any
4
+ // purpose with or without fee is hereby granted, provided that the above
5
+ // copyright notice and this permission notice appear in all copies.
6
+ //
7
+ // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8
+ // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9
+ // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10
+ // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11
+ // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12
+ // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13
+ // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14
+
15
+ import junit.framework.TestCase;
16
+
17
+ /**
18
+ * JUnit unit tests for BCrypt routines
19
+ * @author Damien Miller
20
+ * @version 0.2
21
+ */
22
+ public class TestBCrypt extends TestCase {
23
+ String test_vectors[][] = {
24
+ { "",
25
+ "$2a$06$DCq7YPn5Rq63x1Lad4cll.",
26
+ "$2a$06$DCq7YPn5Rq63x1Lad4cll.TV4S6ytwfsfvkgY8jIucDrjc8deX1s." },
27
+ { "",
28
+ "$2a$08$HqWuK6/Ng6sg9gQzbLrgb.",
29
+ "$2a$08$HqWuK6/Ng6sg9gQzbLrgb.Tl.ZHfXLhvt/SgVyWhQqgqcZ7ZuUtye" },
30
+ { "",
31
+ "$2a$10$k1wbIrmNyFAPwPVPSVa/ze",
32
+ "$2a$10$k1wbIrmNyFAPwPVPSVa/zecw2BCEnBwVS2GbrmgzxFUOqW9dk4TCW" },
33
+ { "",
34
+ "$2a$12$k42ZFHFWqBp3vWli.nIn8u",
35
+ "$2a$12$k42ZFHFWqBp3vWli.nIn8uYyIkbvYRvodzbfbK18SSsY.CsIQPlxO" },
36
+ { "a",
37
+ "$2a$06$m0CrhHm10qJ3lXRY.5zDGO",
38
+ "$2a$06$m0CrhHm10qJ3lXRY.5zDGO3rS2KdeeWLuGmsfGlMfOxih58VYVfxe" },
39
+ { "a",
40
+ "$2a$08$cfcvVd2aQ8CMvoMpP2EBfe",
41
+ "$2a$08$cfcvVd2aQ8CMvoMpP2EBfeodLEkkFJ9umNEfPD18.hUF62qqlC/V." },
42
+ { "a",
43
+ "$2a$10$k87L/MF28Q673VKh8/cPi.",
44
+ "$2a$10$k87L/MF28Q673VKh8/cPi.SUl7MU/rWuSiIDDFayrKk/1tBsSQu4u" },
45
+ { "a",
46
+ "$2a$12$8NJH3LsPrANStV6XtBakCe",
47
+ "$2a$12$8NJH3LsPrANStV6XtBakCez0cKHXVxmvxIlcz785vxAIZrihHZpeS" },
48
+ { "abc",
49
+ "$2a$06$If6bvum7DFjUnE9p2uDeDu",
50
+ "$2a$06$If6bvum7DFjUnE9p2uDeDu0YHzrHM6tf.iqN8.yx.jNN1ILEf7h0i" },
51
+ { "abc",
52
+ "$2a$08$Ro0CUfOqk6cXEKf3dyaM7O",
53
+ "$2a$08$Ro0CUfOqk6cXEKf3dyaM7OhSCvnwM9s4wIX9JeLapehKK5YdLxKcm" },
54
+ { "abc",
55
+ "$2a$10$WvvTPHKwdBJ3uk0Z37EMR.",
56
+ "$2a$10$WvvTPHKwdBJ3uk0Z37EMR.hLA2W6N9AEBhEgrAOljy2Ae5MtaSIUi" },
57
+ { "abc",
58
+ "$2a$12$EXRkfkdmXn2gzds2SSitu.",
59
+ "$2a$12$EXRkfkdmXn2gzds2SSitu.MW9.gAVqa9eLS1//RYtYCmB1eLHg.9q" },
60
+ { "abcdefghijklmnopqrstuvwxyz",
61
+ "$2a$06$.rCVZVOThsIa97pEDOxvGu",
62
+ "$2a$06$.rCVZVOThsIa97pEDOxvGuRRgzG64bvtJ0938xuqzv18d3ZpQhstC" },
63
+ { "abcdefghijklmnopqrstuvwxyz",
64
+ "$2a$08$aTsUwsyowQuzRrDqFflhge",
65
+ "$2a$08$aTsUwsyowQuzRrDqFflhgekJ8d9/7Z3GV3UcgvzQW3J5zMyrTvlz." },
66
+ { "abcdefghijklmnopqrstuvwxyz",
67
+ "$2a$10$fVH8e28OQRj9tqiDXs1e1u",
68
+ "$2a$10$fVH8e28OQRj9tqiDXs1e1uxpsjN0c7II7YPKXua2NAKYvM6iQk7dq" },
69
+ { "abcdefghijklmnopqrstuvwxyz",
70
+ "$2a$12$D4G5f18o7aMMfwasBL7Gpu",
71
+ "$2a$12$D4G5f18o7aMMfwasBL7GpuQWuP3pkrZrOAnqP.bmezbMng.QwJ/pG" },
72
+ { "~!@#$%^&*() ~!@#$%^&*()PNBFRD",
73
+ "$2a$06$fPIsBO8qRqkjj273rfaOI.",
74
+ "$2a$06$fPIsBO8qRqkjj273rfaOI.HtSV9jLDpTbZn782DC6/t7qT67P6FfO" },
75
+ { "~!@#$%^&*() ~!@#$%^&*()PNBFRD",
76
+ "$2a$08$Eq2r4G/76Wv39MzSX262hu",
77
+ "$2a$08$Eq2r4G/76Wv39MzSX262huzPz612MZiYHVUJe/OcOql2jo4.9UxTW" },
78
+ { "~!@#$%^&*() ~!@#$%^&*()PNBFRD",
79
+ "$2a$10$LgfYWkbzEvQ4JakH7rOvHe",
80
+ "$2a$10$LgfYWkbzEvQ4JakH7rOvHe0y8pHKF9OaFgwUZ2q7W2FFZmZzJYlfS" },
81
+ { "~!@#$%^&*() ~!@#$%^&*()PNBFRD",
82
+ "$2a$12$WApznUOJfkEGSmYRfnkrPO",
83
+ "$2a$12$WApznUOJfkEGSmYRfnkrPOr466oFDCaj4b6HY3EXGvfxm43seyhgC" },
84
+ };
85
+
86
+ /**
87
+ * Entry point for unit tests
88
+ * @param args unused
89
+ */
90
+ public static void main(String[] args) {
91
+ junit.textui.TestRunner.run(TestBCrypt.class);
92
+ }
93
+
94
+ /**
95
+ * Test method for 'BCrypt.hashpw(String, String)'
96
+ */
97
+ public void testHashpw() {
98
+ System.out.print("BCrypt.hashpw(): ");
99
+ for (int i = 0; i < test_vectors.length; i++) {
100
+ String plain = test_vectors[i][0];
101
+ String salt = test_vectors[i][1];
102
+ String expected = test_vectors[i][2];
103
+ String hashed = BCrypt.hashpw(plain, salt);
104
+ assertEquals(hashed, expected);
105
+ System.out.print(".");
106
+ }
107
+ System.out.println("");
108
+ }
109
+
110
+ /**
111
+ * Test method for 'BCrypt.gensalt(int)'
112
+ */
113
+ public void testGensaltInt() {
114
+ System.out.print("BCrypt.gensalt(log_rounds):");
115
+ for (int i = 4; i <= 12; i++) {
116
+ System.out.print(" " + Integer.toString(i) + ":");
117
+ for (int j = 0; j < test_vectors.length; j += 4) {
118
+ String plain = test_vectors[j][0];
119
+ String salt = BCrypt.gensalt(i);
120
+ String hashed1 = BCrypt.hashpw(plain, salt);
121
+ String hashed2 = BCrypt.hashpw(plain, hashed1);
122
+ assertEquals(hashed1, hashed2);
123
+ System.out.print(".");
124
+ }
125
+ }
126
+ System.out.println("");
127
+ }
128
+
129
+ /**
130
+ * Test method for 'BCrypt.gensalt()'
131
+ */
132
+ public void testGensalt() {
133
+ System.out.print("BCrypt.gensalt(): ");
134
+ for (int i = 0; i < test_vectors.length; i += 4) {
135
+ String plain = test_vectors[i][0];
136
+ String salt = BCrypt.gensalt();
137
+ String hashed1 = BCrypt.hashpw(plain, salt);
138
+ String hashed2 = BCrypt.hashpw(plain, hashed1);
139
+ assertEquals(hashed1, hashed2);
140
+ System.out.print(".");
141
+ }
142
+ System.out.println("");
143
+ }
144
+
145
+ /**
146
+ * Test method for 'BCrypt.checkpw(String, String)'
147
+ * expecting success
148
+ */
149
+ public void testCheckpw_success() {
150
+ System.out.print("BCrypt.checkpw w/ good passwords: ");
151
+ for (int i = 0; i < test_vectors.length; i++) {
152
+ String plain = test_vectors[i][0];
153
+ String expected = test_vectors[i][2];
154
+ assertTrue(BCrypt.checkpw(plain, expected));
155
+ System.out.print(".");
156
+ }
157
+ System.out.println("");
158
+ }
159
+
160
+ /**
161
+ * Test method for 'BCrypt.checkpw(String, String)'
162
+ * expecting failure
163
+ */
164
+ public void testCheckpw_failure() {
165
+ System.out.print("BCrypt.checkpw w/ bad passwords: ");
166
+ for (int i = 0; i < test_vectors.length; i++) {
167
+ int broken_index = (i + 4) % test_vectors.length;
168
+ String plain = test_vectors[i][0];
169
+ String expected = test_vectors[broken_index][2];
170
+ assertFalse(BCrypt.checkpw(plain, expected));
171
+ System.out.print(".");
172
+ }
173
+ System.out.println("");
174
+ }
175
+
176
+ /**
177
+ * Test for correct hashing of non-US-ASCII passwords
178
+ */
179
+ public void testInternationalChars() {
180
+ System.out.print("BCrypt.hashpw w/ international chars: ");
181
+ String pw1 = "ππππππππ";
182
+ String pw2 = "????????";
183
+
184
+ String h1 = BCrypt.hashpw(pw1, BCrypt.gensalt());
185
+ assertFalse(BCrypt.checkpw(pw2, h1));
186
+ System.out.print(".");
187
+
188
+ String h2 = BCrypt.hashpw(pw2, BCrypt.gensalt());
189
+ assertFalse(BCrypt.checkpw(pw1, h2));
190
+ System.out.print(".");
191
+ System.out.println("");
192
+ }
193
+
194
+ }
@@ -0,0 +1,82 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "..", "spec_helper"))
2
+
3
+ describe "The BCrypt engine" do
4
+ specify "should calculate the optimal cost factor to fit in a specific time" do
5
+ first = BCrypt::Engine.calibrate(100)
6
+ second = BCrypt::Engine.calibrate(400)
7
+ second.should > first
8
+ end
9
+ end
10
+
11
+ describe "Generating BCrypt salts" do
12
+
13
+ specify "should produce strings" do
14
+ BCrypt::Engine.generate_salt.should be_an_instance_of(String)
15
+ end
16
+
17
+ specify "should produce random data" do
18
+ BCrypt::Engine.generate_salt.should_not equal(BCrypt::Engine.generate_salt)
19
+ end
20
+
21
+ specify "should raise a InvalidCostError if the cost parameter isn't numeric" do
22
+ lambda { BCrypt::Engine.generate_salt('woo') }.should raise_error(BCrypt::Errors::InvalidCost)
23
+ end
24
+
25
+ specify "should raise a InvalidCostError if the cost parameter isn't greater than 0" do
26
+ lambda { BCrypt::Engine.generate_salt(-1) }.should raise_error(BCrypt::Errors::InvalidCost)
27
+ end
28
+ end
29
+
30
+ describe "Autodetecting of salt cost" do
31
+
32
+ specify "should work" do
33
+ BCrypt::Engine.autodetect_cost("$2a$08$hRx2IVeHNsTSYYtUWn61Ou").should eq 8
34
+ BCrypt::Engine.autodetect_cost("$2a$05$XKd1bMnLgUnc87qvbAaCUu").should eq 5
35
+ BCrypt::Engine.autodetect_cost("$2a$13$Lni.CZ6z5A7344POTFBBV.").should eq 13
36
+ end
37
+
38
+ end
39
+
40
+ describe "Generating BCrypt hashes" do
41
+
42
+ class MyInvalidSecret
43
+ undef to_s
44
+ end
45
+
46
+ before :each do
47
+ @salt = BCrypt::Engine.generate_salt(4)
48
+ @password = "woo"
49
+ end
50
+
51
+ specify "should produce a string" do
52
+ BCrypt::Engine.hash_secret(@password, @salt).should be_an_instance_of(String)
53
+ end
54
+
55
+ specify "should raise an InvalidSalt error if the salt is invalid" do
56
+ lambda { BCrypt::Engine.hash_secret(@password, 'nino') }.should raise_error(BCrypt::Errors::InvalidSalt)
57
+ end
58
+
59
+ specify "should raise an InvalidSecret error if the secret is invalid" do
60
+ lambda { BCrypt::Engine.hash_secret(MyInvalidSecret.new, @salt) }.should raise_error(BCrypt::Errors::InvalidSecret)
61
+ lambda { BCrypt::Engine.hash_secret(nil, @salt) }.should_not raise_error(BCrypt::Errors::InvalidSecret)
62
+ lambda { BCrypt::Engine.hash_secret(false, @salt) }.should_not raise_error(BCrypt::Errors::InvalidSecret)
63
+ end
64
+
65
+ specify "should call #to_s on the secret and use the return value as the actual secret data" do
66
+ BCrypt::Engine.hash_secret(false, @salt).should == BCrypt::Engine.hash_secret("false", @salt)
67
+ end
68
+
69
+ specify "should be interoperable with other implementations" do
70
+ # test vectors from the OpenWall implementation <http://www.openwall.com/crypt/>
71
+ test_vectors = [
72
+ ["U*U", "$2a$05$CCCCCCCCCCCCCCCCCCCCC.", "$2a$05$CCCCCCCCCCCCCCCCCCCCC.E5YPO9kmyuRGyh0XouQYb4YMJKvyOeW"],
73
+ ["U*U*", "$2a$05$CCCCCCCCCCCCCCCCCCCCC.", "$2a$05$CCCCCCCCCCCCCCCCCCCCC.VGOzA784oUp/Z0DY336zx7pLYAy0lwK"],
74
+ ["U*U*U", "$2a$05$XXXXXXXXXXXXXXXXXXXXXO", "$2a$05$XXXXXXXXXXXXXXXXXXXXXOAcXxm9kjPGEMsLznoKqmqw7tc8WCx4a"],
75
+ ["", "$2a$05$CCCCCCCCCCCCCCCCCCCCC.", "$2a$05$CCCCCCCCCCCCCCCCCCCCC.7uG0VCzI2bS7j6ymqJi9CdcdxiRTWNy"],
76
+ ["0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", "$2a$05$abcdefghijklmnopqrstuu", "$2a$05$abcdefghijklmnopqrstuu5s2v8.iXieOjg/.AySBTTZIIVFJeBui"]
77
+ ]
78
+ for secret, salt, test_vector in test_vectors
79
+ BCrypt::Engine.hash_secret(secret, salt).should eql(test_vector)
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,82 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "..", "spec_helper"))
2
+
3
+ describe "Creating a hashed password" do
4
+
5
+ before :each do
6
+ @secret = "wheedle"
7
+ @password = BCrypt::Password.create(@secret, :cost => 4)
8
+ end
9
+
10
+ specify "should return a BCrypt::Password" do
11
+ @password.should be_an_instance_of(BCrypt::Password)
12
+ end
13
+
14
+ specify "should return a valid bcrypt password" do
15
+ lambda { BCrypt::Password.new(@password) }.should_not raise_error
16
+ end
17
+
18
+ specify "should behave normally if the secret is not a string" do
19
+ lambda { BCrypt::Password.create(nil) }.should_not raise_error(BCrypt::Errors::InvalidSecret)
20
+ lambda { BCrypt::Password.create({:woo => "yeah"}) }.should_not raise_error(BCrypt::Errors::InvalidSecret)
21
+ lambda { BCrypt::Password.create(false) }.should_not raise_error(BCrypt::Errors::InvalidSecret)
22
+ end
23
+
24
+ specify "should tolerate empty string secrets" do
25
+ lambda { BCrypt::Password.create( "\n".chop ) }.should_not raise_error
26
+ lambda { BCrypt::Password.create( "" ) }.should_not raise_error
27
+ lambda { BCrypt::Password.create( String.new ) }.should_not raise_error
28
+ end
29
+ end
30
+
31
+ describe "Reading a hashed password" do
32
+ before :each do
33
+ @secret = "U*U"
34
+ @hash = "$2a$05$CCCCCCCCCCCCCCCCCCCCC.E5YPO9kmyuRGyh0XouQYb4YMJKvyOeW"
35
+ end
36
+
37
+ specify "the cost is too damn high" do
38
+ lambda {
39
+ BCrypt::Password.create("hello", :cost => 32)
40
+ }.should raise_error(ArgumentError)
41
+ end
42
+
43
+ specify "should read the version, cost, salt, and hash" do
44
+ password = BCrypt::Password.new(@hash)
45
+ password.version.should eql("2a")
46
+ password.cost.should equal(5)
47
+ password.salt.should eql("$2a$05$CCCCCCCCCCCCCCCCCCCCC.")
48
+ password.salt.class.should eq String
49
+ password.checksum.should eq("E5YPO9kmyuRGyh0XouQYb4YMJKvyOeW")
50
+ password.checksum.class.should eq String
51
+ password.to_s.should eql(@hash)
52
+ end
53
+
54
+ specify "should raise an InvalidHashError when given an invalid hash" do
55
+ lambda { BCrypt::Password.new('weedle') }.should raise_error(BCrypt::Errors::InvalidHash)
56
+ end
57
+ end
58
+
59
+ describe "Comparing a hashed password with a secret" do
60
+ before :each do
61
+ @secret = "U*U"
62
+ @hash = "$2a$05$CCCCCCCCCCCCCCCCCCCCC.E5YPO9kmyuRGyh0XouQYb4YMJKvyOeW"
63
+ @password = BCrypt::Password.create(@secret)
64
+ end
65
+
66
+ specify "should compare successfully to the original secret" do
67
+ (@password == @secret).should be(true)
68
+ end
69
+
70
+ specify "should compare unsuccessfully to anything besides original secret" do
71
+ (@password == "@secret").should be(false)
72
+ end
73
+ end
74
+
75
+ describe "Validating a generated salt" do
76
+ specify "should not accept an invalid salt" do
77
+ BCrypt::Engine.valid_salt?("invalid").should eq(false)
78
+ end
79
+ specify "should accept a valid salt" do
80
+ BCrypt::Engine.valid_salt?(BCrypt::Engine.generate_salt).should eq(true)
81
+ end
82
+ end
@@ -0,0 +1,2 @@
1
+ $:.unshift File.expand_path('../../lib', __FILE__)
2
+ require 'bcrypt'
metadata ADDED
@@ -0,0 +1,104 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bcrypt-ruby-maglev-
3
+ version: !ruby/object:Gem::Version
4
+ version: 3.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Coda Hale
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2011-09-26 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rake-compiler
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: rspec
27
+ type: :development
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ version:
35
+ description: " bcrypt() is a sophisticated and secure hash algorithm designed by The OpenBSD project\n for hashing passwords. bcrypt-ruby provides a simple, humane wrapper for safely handling\n passwords.\n"
36
+ email: coda.hale@gmail.com
37
+ executables: []
38
+
39
+ extensions:
40
+ - ext/mri/extconf.rb
41
+ extra_rdoc_files:
42
+ - README.md
43
+ - COPYING
44
+ - CHANGELOG
45
+ - lib/bcrypt.rb
46
+ files:
47
+ - .gitignore
48
+ - .rspec
49
+ - CHANGELOG
50
+ - COPYING
51
+ - Gemfile
52
+ - Gemfile.lock
53
+ - README.md
54
+ - Rakefile
55
+ - bcrypt-ruby.gemspec
56
+ - ext/jruby/bcrypt_jruby/BCrypt.java
57
+ - ext/mri/bcrypt_ext.c
58
+ - ext/mri/crypt.c
59
+ - ext/mri/crypt.h
60
+ - ext/mri/crypt_blowfish.c
61
+ - ext/mri/crypt_gensalt.c
62
+ - ext/mri/extconf.rb
63
+ - ext/mri/ow-crypt.h
64
+ - ext/mri/wrapper.c
65
+ - lib/bcrypt.rb
66
+ - spec/TestBCrypt.java
67
+ - spec/bcrypt/engine_spec.rb
68
+ - spec/bcrypt/password_spec.rb
69
+ - spec/spec_helper.rb
70
+ has_rdoc: true
71
+ homepage: http://bcrypt-ruby.rubyforge.org
72
+ licenses: []
73
+
74
+ post_install_message:
75
+ rdoc_options:
76
+ - --title
77
+ - bcrypt-ruby
78
+ - --line-numbers
79
+ - --inline-source
80
+ - --main
81
+ - README.md
82
+ require_paths:
83
+ - lib
84
+ required_ruby_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: "0"
89
+ version:
90
+ required_rubygems_version: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: "0"
95
+ version:
96
+ requirements: []
97
+
98
+ rubyforge_project: bcrypt-ruby
99
+ rubygems_version: 1.3.5
100
+ signing_key:
101
+ specification_version: 3
102
+ summary: OpenBSD's bcrypt() password hashing algorithm.
103
+ test_files: []
104
+