bcrypt-ruby 3.1.2.rc1-x64-mingw32
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.
- data/.gitignore +10 -0
- data/.rspec +3 -0
- data/.travis.yml +11 -0
- data/CHANGELOG +59 -0
- data/COPYING +28 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +35 -0
- data/README.md +204 -0
- data/Rakefile +74 -0
- data/bcrypt-ruby.gemspec +30 -0
- data/ext/jruby/bcrypt_jruby/BCrypt.java +752 -0
- data/ext/mri/bcrypt_ext.c +64 -0
- data/ext/mri/crypt.c +57 -0
- data/ext/mri/crypt.h +13 -0
- data/ext/mri/crypt_blowfish.c +786 -0
- data/ext/mri/crypt_gensalt.c +111 -0
- data/ext/mri/extconf.rb +17 -0
- data/ext/mri/ow-crypt.h +35 -0
- data/ext/mri/wrapper.c +262 -0
- data/lib/bcrypt.rb +21 -0
- data/lib/bcrypt/engine.rb +120 -0
- data/lib/bcrypt/error.rb +22 -0
- data/lib/bcrypt/password.rb +87 -0
- data/spec/TestBCrypt.java +194 -0
- data/spec/bcrypt/engine_spec.rb +82 -0
- data/spec/bcrypt/error_spec.rb +37 -0
- data/spec/bcrypt/password_spec.rb +123 -0
- data/spec/spec_helper.rb +2 -0
- metadata +151 -0
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/CHANGELOG
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
1.0.0 Feb 27 2007
|
2
|
+
- Initial release.
|
3
|
+
|
4
|
+
2.0.0 Mar 07 2007
|
5
|
+
- Removed BCrypt::Password#exactly_equals -- use BCrypt::Password#eql? instead.
|
6
|
+
- Added BCrypt::Password#is_password?.
|
7
|
+
- Refactored out BCrypt::Internals into more useful BCrypt::Engine.
|
8
|
+
- Added validation of secrets -- nil is not healthy.
|
9
|
+
|
10
|
+
2.0.1 Mar 09 2007
|
11
|
+
- Fixed load path issues
|
12
|
+
- Fixed crashes when hashing weird values (e.g., false, etc.)
|
13
|
+
|
14
|
+
2.0.2 Jun 06 2007
|
15
|
+
- Fixed example code in the README [Winson]
|
16
|
+
- Fixed Solaris compatibility [Jeremy LaTrasse, Twitter crew]
|
17
|
+
|
18
|
+
2.0.3 May 07 2008
|
19
|
+
- Made exception classes descend from StandardError, not Exception [Dan42]
|
20
|
+
- Changed BCrypt::Engine.hash to BCrypt::Engine.hash_secret to avoid Merb
|
21
|
+
sorting issues. [Lee Pope]
|
22
|
+
|
23
|
+
2.0.4 Mar 09 2009
|
24
|
+
- Added Ruby 1.9 compatibility. [Genki Takiuchi]
|
25
|
+
- Fixed segfaults on some different types of empty strings. [Mike Pomraning]
|
26
|
+
|
27
|
+
2.0.5 Mar 11 2009
|
28
|
+
- Fixed Ruby 1.8.5 compatibility. [Mike Pomraning]
|
29
|
+
|
30
|
+
2.1.0 Aug 12 2009
|
31
|
+
- Improved code coverage, unit tests, and build chain. [Hongli Lai]
|
32
|
+
- Ruby 1.9 compatibility fixes. [Hongli Lai]
|
33
|
+
- JRuby support, using Damien Miller's jBCrypt. [Hongli Lai]
|
34
|
+
- Ruby 1.9 GIL releasing for high-cost hashes. [Hongli Lai]
|
35
|
+
|
36
|
+
2.1.1 Aug 14 2009
|
37
|
+
- JVM 1.4/1.5 compatibility [Hongli Lai]
|
38
|
+
|
39
|
+
2.1.2 Sep 16 2009
|
40
|
+
- Fixed support for Solaris, OpenSolaris.
|
41
|
+
|
42
|
+
3.0.0 Aug 24 2011
|
43
|
+
- Bcrypt C implementation replaced with a public domain implementation.
|
44
|
+
- License changed to MIT
|
45
|
+
|
46
|
+
3.0.1 Sep 12 2011
|
47
|
+
- create raises an exception if the cost is higher than 31. GH #27
|
48
|
+
|
49
|
+
3.1.0 May 07 2013
|
50
|
+
- Add BCrypt::Password.valid_hash?(str) to check if a string is a valid bcrypt password hash
|
51
|
+
- BCrypt::Password cost should be set to DEFAULT_COST if nil
|
52
|
+
- Add BCrypt::Engine.cost attribute for getting/setting a default cost externally
|
53
|
+
|
54
|
+
3.1.1 Jul 10 2013
|
55
|
+
- Remove support for Ruby 1.8 in compiled win32 binaries
|
56
|
+
|
57
|
+
3.1.2 Aug 23 2013
|
58
|
+
- Add support for Ruby 1.8 and 2.0 (in addition to 1.9) in compiled Windows binaries
|
59
|
+
- Add support for 64-bit Windows
|
data/COPYING
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
(The MIT License)
|
2
|
+
|
3
|
+
Copyright 2007-2011:
|
4
|
+
|
5
|
+
* Coda Hale <coda.hale@gmail.com>
|
6
|
+
|
7
|
+
C implementation of the BCrypt algorithm by Solar Designer and placed in the
|
8
|
+
public domain.
|
9
|
+
jBCrypt is Copyright (c) 2006 Damien Miller <djm@mindrot.org>.
|
10
|
+
|
11
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
12
|
+
a copy of this software and associated documentation files (the
|
13
|
+
'Software'), to deal in the Software without restriction, including
|
14
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
15
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
16
|
+
permit persons to whom the Software is furnished to do so, subject to
|
17
|
+
the following conditions:
|
18
|
+
|
19
|
+
The above copyright notice and this permission notice shall be
|
20
|
+
included in all copies or substantial portions of the Software.
|
21
|
+
|
22
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
23
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
24
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
25
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
26
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
27
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
28
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
bcrypt-ruby (3.1.2.rc1)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
diff-lcs (1.2.4)
|
10
|
+
json (1.7.3)
|
11
|
+
json (1.7.3-java)
|
12
|
+
rake (10.1.0)
|
13
|
+
rake-compiler (0.9.1)
|
14
|
+
rake
|
15
|
+
rdoc (3.12)
|
16
|
+
json (~> 1.4)
|
17
|
+
rspec (2.13.0)
|
18
|
+
rspec-core (~> 2.13.0)
|
19
|
+
rspec-expectations (~> 2.13.0)
|
20
|
+
rspec-mocks (~> 2.13.0)
|
21
|
+
rspec-core (2.13.1)
|
22
|
+
rspec-expectations (2.13.0)
|
23
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
24
|
+
rspec-mocks (2.13.1)
|
25
|
+
|
26
|
+
PLATFORMS
|
27
|
+
java
|
28
|
+
ruby
|
29
|
+
x86-mingw32
|
30
|
+
|
31
|
+
DEPENDENCIES
|
32
|
+
bcrypt-ruby!
|
33
|
+
rake-compiler (~> 0.9.0)
|
34
|
+
rdoc
|
35
|
+
rspec
|
data/README.md
ADDED
@@ -0,0 +1,204 @@
|
|
1
|
+
# bcrypt-ruby
|
2
|
+
|
3
|
+
An easy way to keep your users' passwords secure.
|
4
|
+
|
5
|
+
* http://bcrypt-ruby.rubyforge.org/
|
6
|
+
* http://github.com/codahale/bcrypt-ruby/tree/master
|
7
|
+
|
8
|
+
[](https://travis-ci.org/codahale/bcrypt-ruby)
|
9
|
+
|
10
|
+
## Why you should use `bcrypt()`
|
11
|
+
|
12
|
+
If you store user passwords in the clear, then an attacker who steals a copy of your database has a giant list of emails
|
13
|
+
and passwords. Some of your users will only have one password -- for their email account, for their banking account, for
|
14
|
+
your application. A simple hack could escalate into massive identity theft.
|
15
|
+
|
16
|
+
It's your responsibility as a web developer to make your web application secure -- blaming your users for not being
|
17
|
+
security experts is not a professional response to risk.
|
18
|
+
|
19
|
+
`bcrypt()` allows you to easily harden your application against these kinds of attacks.
|
20
|
+
|
21
|
+
*Note*: JRuby versions of bcrypt-ruby `<= 2.1.3` had a [security
|
22
|
+
vulnerability](http://www.mindrot.org/files/jBCrypt/internat.adv) that
|
23
|
+
was fixed in `>= 2.1.4`. If you used a vulnerable version to hash
|
24
|
+
passwords with international characters in them, you will need to
|
25
|
+
re-hash those passwords. This vulernability only affected the JRuby gem.
|
26
|
+
|
27
|
+
## How to install bcrypt
|
28
|
+
|
29
|
+
gem install bcrypt-ruby
|
30
|
+
|
31
|
+
The bcrypt-ruby gem is available on the following ruby platforms:
|
32
|
+
|
33
|
+
* JRuby
|
34
|
+
* RubyInstaller 1.8, 1.9, and 2.0 builds on win32
|
35
|
+
* Any 1.8, 1.9, or 2.0 ruby on a BSD/OSX/Linux system with a compiler
|
36
|
+
|
37
|
+
## How to use `bcrypt()` in your Rails application
|
38
|
+
|
39
|
+
*Note*: Rails versions >= 3 ship with `ActiveModel::SecurePassword` which uses bcrypt-ruby.
|
40
|
+
`has_secure_password` [docs](http://api.rubyonrails.org/classes/ActiveModel/SecurePassword/ClassMethods.html#method-i-has_secure_password)
|
41
|
+
implements a similar authentication strategy to the code below.
|
42
|
+
|
43
|
+
### The _User_ model
|
44
|
+
|
45
|
+
require 'bcrypt'
|
46
|
+
|
47
|
+
class User < ActiveRecord::Base
|
48
|
+
# users.password_hash in the database is a :string
|
49
|
+
include BCrypt
|
50
|
+
|
51
|
+
def password
|
52
|
+
@password ||= Password.new(password_hash)
|
53
|
+
end
|
54
|
+
|
55
|
+
def password=(new_password)
|
56
|
+
@password = Password.create(new_password)
|
57
|
+
self.password_hash = @password
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
### Creating an account
|
62
|
+
|
63
|
+
def create
|
64
|
+
@user = User.new(params[:user])
|
65
|
+
@user.password = params[:password]
|
66
|
+
@user.save!
|
67
|
+
end
|
68
|
+
|
69
|
+
### Authenticating a user
|
70
|
+
|
71
|
+
def login
|
72
|
+
@user = User.find_by_email(params[:email])
|
73
|
+
if @user.password == params[:password]
|
74
|
+
give_token
|
75
|
+
else
|
76
|
+
redirect_to home_url
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
### If a user forgets their password?
|
81
|
+
|
82
|
+
# assign them a random one and mail it to them, asking them to change it
|
83
|
+
def forgot_password
|
84
|
+
@user = User.find_by_email(params[:email])
|
85
|
+
random_password = Array.new(10).map { (65 + rand(58)).chr }.join
|
86
|
+
@user.password = random_password
|
87
|
+
@user.save!
|
88
|
+
Mailer.create_and_deliver_password_change(@user, random_password)
|
89
|
+
end
|
90
|
+
|
91
|
+
## How to use bcrypt-ruby in general
|
92
|
+
|
93
|
+
require 'bcrypt'
|
94
|
+
|
95
|
+
my_password = BCrypt::Password.create("my password")
|
96
|
+
#=> "$2a$10$vI8aWBnW3fID.ZQ4/zo1G.q1lRps.9cGLcZEiGDMVr5yUP1KUOYTa"
|
97
|
+
|
98
|
+
my_password.version #=> "2a"
|
99
|
+
my_password.cost #=> 10
|
100
|
+
my_password == "my password" #=> true
|
101
|
+
my_password == "not my password" #=> false
|
102
|
+
|
103
|
+
my_password = BCrypt::Password.new("$2a$10$vI8aWBnW3fID.ZQ4/zo1G.q1lRps.9cGLcZEiGDMVr5yUP1KUOYTa")
|
104
|
+
my_password == "my password" #=> true
|
105
|
+
my_password == "not my password" #=> false
|
106
|
+
|
107
|
+
Check the rdocs for more details -- BCrypt, BCrypt::Password.
|
108
|
+
|
109
|
+
## How `bcrypt()` works
|
110
|
+
|
111
|
+
`bcrypt()` is a hashing algorithm designed by Niels Provos and David Mazières of the OpenBSD Project.
|
112
|
+
|
113
|
+
### Background
|
114
|
+
|
115
|
+
Hash algorithms take a chunk of data (e.g., your user's password) and create a "digital fingerprint," or hash, of it.
|
116
|
+
Because this process is not reversible, there's no way to go from the hash back to the password.
|
117
|
+
|
118
|
+
In other words:
|
119
|
+
|
120
|
+
hash(p) #=> <unique gibberish>
|
121
|
+
|
122
|
+
You can store the hash and check it against a hash made of a potentially valid password:
|
123
|
+
|
124
|
+
<unique gibberish> =? hash(just_entered_password)
|
125
|
+
|
126
|
+
### Rainbow Tables
|
127
|
+
|
128
|
+
But even this has weaknesses -- attackers can just run lists of possible passwords through the same algorithm, store the
|
129
|
+
results in a big database, and then look up the passwords by their hash:
|
130
|
+
|
131
|
+
PrecomputedPassword.find_by_hash(<unique gibberish>).password #=> "secret1"
|
132
|
+
|
133
|
+
### Salts
|
134
|
+
|
135
|
+
The solution to this is to add a small chunk of random data -- called a salt -- to the password before it's hashed:
|
136
|
+
|
137
|
+
hash(salt + p) #=> <really unique gibberish>
|
138
|
+
|
139
|
+
The salt is then stored along with the hash in the database, and used to check potentially valid passwords:
|
140
|
+
|
141
|
+
<really unique gibberish> =? hash(salt + just_entered_password)
|
142
|
+
|
143
|
+
bcrypt-ruby automatically handles the storage and generation of these salts for you.
|
144
|
+
|
145
|
+
Adding a salt means that an attacker has to have a gigantic database for each unique salt -- for a salt made of 4
|
146
|
+
letters, that's 456,976 different databases. Pretty much no one has that much storage space, so attackers try a
|
147
|
+
different, slower method -- throw a list of potential passwords at each individual password:
|
148
|
+
|
149
|
+
hash(salt + "aadvark") =? <really unique gibberish>
|
150
|
+
hash(salt + "abacus") =? <really unique gibberish>
|
151
|
+
etc.
|
152
|
+
|
153
|
+
This is much slower than the big database approach, but most hash algorithms are pretty quick -- and therein lies the
|
154
|
+
problem. Hash algorithms aren't usually designed to be slow, they're designed to turn gigabytes of data into secure
|
155
|
+
fingerprints as quickly as possible. `bcrypt()`, though, is designed to be computationally expensive:
|
156
|
+
|
157
|
+
Ten thousand iterations:
|
158
|
+
user system total real
|
159
|
+
md5 0.070000 0.000000 0.070000 ( 0.070415)
|
160
|
+
bcrypt 22.230000 0.080000 22.310000 ( 22.493822)
|
161
|
+
|
162
|
+
If an attacker was using Ruby to check each password, they could check ~140,000 passwords a second with MD5 but only
|
163
|
+
~450 passwords a second with `bcrypt()`.
|
164
|
+
|
165
|
+
### Cost Factors
|
166
|
+
|
167
|
+
In addition, `bcrypt()` allows you to increase the amount of work required to hash a password as computers get faster. Old
|
168
|
+
passwords will still work fine, but new passwords can keep up with the times.
|
169
|
+
|
170
|
+
The default cost factor used by bcrypt-ruby is 10, which is fine for session-based authentication. If you are using a
|
171
|
+
stateless authentication architecture (e.g., HTTP Basic Auth), you will want to lower the cost factor to reduce your
|
172
|
+
server load and keep your request times down. This will lower the security provided you, but there are few alternatives.
|
173
|
+
|
174
|
+
To change the default cost factor used by bcrypt-ruby, use `BCrypt::Engine.cost = new_value`:
|
175
|
+
|
176
|
+
BCrypt::Password.create('secret').cost
|
177
|
+
#=> 10, the default provided by bcrypt-ruby
|
178
|
+
|
179
|
+
# set a new default cost
|
180
|
+
BCrypt::Engine.cost = 8
|
181
|
+
BCrypt::Password.create('secret').cost
|
182
|
+
#=> 8
|
183
|
+
|
184
|
+
The default cost can be overridden as needed by passing an options hash with a different cost:
|
185
|
+
|
186
|
+
BCrypt::Password.create('secret', :cost => 6).cost #=> 6
|
187
|
+
|
188
|
+
## More Information
|
189
|
+
|
190
|
+
`bcrypt()` is currently used as the default password storage hash in OpenBSD, widely regarded as the most secure operating
|
191
|
+
system available.
|
192
|
+
|
193
|
+
For a more technical explanation of the algorithm and its design criteria, please read Niels Provos and David Mazières'
|
194
|
+
Usenix99 paper:
|
195
|
+
http://www.usenix.org/events/usenix99/provos.html
|
196
|
+
|
197
|
+
If you'd like more down-to-earth advice regarding cryptography, I suggest reading <i>Practical Cryptography</i> by Niels
|
198
|
+
Ferguson and Bruce Schneier:
|
199
|
+
http://www.schneier.com/book-practical.html
|
200
|
+
|
201
|
+
# Etc
|
202
|
+
|
203
|
+
* Author :: Coda Hale <coda.hale@gmail.com>
|
204
|
+
* Website :: http://blog.codahale.com
|
data/Rakefile
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'rspec/core/rake_task'
|
2
|
+
require 'rubygems/package_task'
|
3
|
+
require 'rake/extensiontask'
|
4
|
+
require 'rake/javaextensiontask'
|
5
|
+
require 'rake/contrib/rubyforgepublisher'
|
6
|
+
require 'rake/clean'
|
7
|
+
require 'rdoc/task'
|
8
|
+
require 'benchmark'
|
9
|
+
|
10
|
+
CLEAN.include(
|
11
|
+
"ext/mri/*.o",
|
12
|
+
"ext/mri/*.bundle",
|
13
|
+
"ext/mri/*.so",
|
14
|
+
"ext/jruby/bcrypt_jruby/*.class"
|
15
|
+
)
|
16
|
+
CLOBBER.include(
|
17
|
+
"ext/mri/Makefile",
|
18
|
+
"doc/coverage",
|
19
|
+
"pkg"
|
20
|
+
)
|
21
|
+
GEMSPEC = eval(File.read(File.expand_path("../bcrypt-ruby.gemspec", __FILE__)))
|
22
|
+
|
23
|
+
task :default => [:compile, :spec]
|
24
|
+
|
25
|
+
desc "Run all specs"
|
26
|
+
RSpec::Core::RakeTask.new do |t|
|
27
|
+
t.pattern = 'spec/**/*_spec.rb'
|
28
|
+
t.ruby_opts = '-w'
|
29
|
+
end
|
30
|
+
|
31
|
+
desc "Run all specs, with coverage testing"
|
32
|
+
RSpec::Core::RakeTask.new(:rcov) do |t|
|
33
|
+
t.pattern = 'spec/**/*_spec.rb'
|
34
|
+
t.rcov = true
|
35
|
+
t.rcov_path = 'doc/coverage'
|
36
|
+
t.rcov_opts = ['--exclude', 'rspec,diff-lcs,rcov,_spec,_helper']
|
37
|
+
end
|
38
|
+
|
39
|
+
desc 'Generate RDoc'
|
40
|
+
RDoc::Task.new do |rdoc|
|
41
|
+
rdoc.rdoc_dir = 'doc/rdoc'
|
42
|
+
rdoc.options += GEMSPEC.rdoc_options
|
43
|
+
rdoc.template = ENV['TEMPLATE'] if ENV['TEMPLATE']
|
44
|
+
rdoc.rdoc_files.include(*GEMSPEC.extra_rdoc_files)
|
45
|
+
end
|
46
|
+
|
47
|
+
Gem::PackageTask.new(GEMSPEC) do |pkg|
|
48
|
+
pkg.need_zip = true
|
49
|
+
pkg.need_tar = true
|
50
|
+
end
|
51
|
+
|
52
|
+
if RUBY_PLATFORM =~ /java/
|
53
|
+
Rake::JavaExtensionTask.new('bcrypt_ext', GEMSPEC) do |ext|
|
54
|
+
ext.ext_dir = 'ext/jruby'
|
55
|
+
end
|
56
|
+
else
|
57
|
+
Rake::ExtensionTask.new("bcrypt_ext", GEMSPEC) do |ext|
|
58
|
+
ext.ext_dir = 'ext/mri'
|
59
|
+
ext.cross_compile = true
|
60
|
+
ext.cross_platform = ['x86-mingw32', 'x86-mswin32-60', 'x64-mingw32']
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
desc "Run a set of benchmarks on the compiled extension."
|
65
|
+
task :benchmark do
|
66
|
+
TESTS = 100
|
67
|
+
TEST_PWD = "this is a test"
|
68
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "lib", "bcrypt"))
|
69
|
+
Benchmark.bmbm do |results|
|
70
|
+
4.upto(10) do |n|
|
71
|
+
results.report("cost #{n}:") { TESTS.times { BCrypt::Password.create(TEST_PWD, :cost => n) } }
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
data/bcrypt-ruby.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'bcrypt-ruby'
|
3
|
+
s.version = '3.1.2.rc1'
|
4
|
+
|
5
|
+
s.summary = "OpenBSD's bcrypt() password hashing algorithm."
|
6
|
+
s.description = <<-EOF
|
7
|
+
bcrypt() is a sophisticated and secure hash algorithm designed by The OpenBSD project
|
8
|
+
for hashing passwords. bcrypt-ruby provides a simple, humane wrapper for safely handling
|
9
|
+
passwords.
|
10
|
+
EOF
|
11
|
+
|
12
|
+
s.files = `git ls-files`.split("\n")
|
13
|
+
s.require_path = 'lib'
|
14
|
+
|
15
|
+
s.add_development_dependency 'rake-compiler', '~> 0.9.0'
|
16
|
+
s.add_development_dependency 'rspec'
|
17
|
+
s.add_development_dependency 'rdoc'
|
18
|
+
|
19
|
+
s.has_rdoc = true
|
20
|
+
s.rdoc_options += ['--title', 'bcrypt-ruby', '--line-numbers', '--inline-source', '--main', 'README.md']
|
21
|
+
s.extra_rdoc_files += ['README.md', 'COPYING', 'CHANGELOG', *Dir['lib/**/*.rb']]
|
22
|
+
|
23
|
+
s.extensions = 'ext/mri/extconf.rb'
|
24
|
+
|
25
|
+
s.authors = ["Coda Hale"]
|
26
|
+
s.email = "coda.hale@gmail.com"
|
27
|
+
s.homepage = "http://bcrypt-ruby.rubyforge.org"
|
28
|
+
s.rubyforge_project = "bcrypt-ruby"
|
29
|
+
s.license = "MIT"
|
30
|
+
end
|