Skip to content

Commit

Permalink
Finish JRuby support.
Browse files Browse the repository at this point in the history
Signed-off-by: Coda Hale <coda.hale@gmail.com>
  • Loading branch information
FooBarWidget authored and codahale committed Aug 12, 2009
1 parent 1354343 commit 8f7acf4
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 22 deletions.
33 changes: 27 additions & 6 deletions Rakefile
Expand Up @@ -15,7 +15,9 @@ PKG_FILES = FileList[
'spec/**/*.rb',
'ext/*.c',
'ext/*.h',
'ext/*.rb'
'ext/*.rb',
'ext/jruby/bcrypt_jruby/BCrypt.java',
'ext/jruby/bcrypt_jruby/BCrypt.class'
]
CLEAN.include(
"ext/*.o",
Expand Down Expand Up @@ -81,11 +83,30 @@ Rake::GemPackageTask.new(spec) do |pkg|
pkg.need_tar = true
end

desc "Clean, then compile the extension."
task :compile => [:clean] do
Dir.chdir('ext') do
ruby "extconf.rb"
sh "make"
desc "Clean, then compile the extension that's native to the current Ruby compiler."
if RUBY_PLATFORM == "java"
task :compile => 'compile:jruby'
else
task :compile => 'compile:mri'
end

namespace :compile do
desc "CLean, then compile all extensions"
task :all => [:mri, :jruby]

desc "Clean, then compile the MRI extension"
task :mri => :clean do
Dir.chdir('ext') do
ruby "extconf.rb"
sh "make"
end
end

desc "Clean, then compile the JRuby extension"
task :jruby => :clean do
Dir.chdir('ext/jruby/bcrypt_jruby') do
sh "javac BCrypt.java"
end
end
end

Expand Down
23 changes: 18 additions & 5 deletions ext/extconf.rb
@@ -1,5 +1,18 @@
require "mkmf"
dir_config("bcrypt_ext")
# enable this when we're feeling nitpicky
# CONFIG['CC'] << " -Wall "
create_makefile("bcrypt_ext")
if RUBY_PLATFORM == "java"
# Don't do anything when run in JRuby; this allows gem installation to pass.
# We need to write a dummy Makefile so that RubyGems doesn't think compilation
# failed.
File.open('Makefile', 'w') do |f|
f.puts "all:"
f.puts "\t@true"
f.puts "install:"
f.puts "\t@true"
end
exit 0
else
require "mkmf"
dir_config("bcrypt_ext")
# enable this when we're feeling nitpicky
# CONFIG['CC'] << " -Wall "
create_makefile("bcrypt_ext")
end
44 changes: 33 additions & 11 deletions lib/bcrypt.rb
@@ -1,8 +1,14 @@
# A wrapper for OpenBSD's bcrypt/crypt_blowfish password-hashing algorithm.

$: << "ext"
require "bcrypt_ext"
require "openssl"
if RUBY_PLATFORM == "java"
require 'java'
$CLASSPATH << File.expand_path(File.join(File.dirname(__FILE__), "..", "ext", "jruby"))
else
$LOAD_PATH.unshift(File.expand_path(File.join(File.dirname(__FILE__), "..", "ext")))
puts $LOAD_PATH
require "bcrypt_ext"
require "openssl"
end

# A Ruby library implementing OpenBSD's bcrypt()/crypt_blowfish algorithm for
# hashing passwords.
Expand All @@ -14,24 +20,32 @@ class InvalidCost < StandardError; end # The cost parameter provided to bcryp
class InvalidSecret < StandardError; end # The secret parameter provided to bcrypt() is invalid.
end

# A Ruby wrapper for the bcrypt() extension calls.
# A Ruby wrapper for the bcrypt() C extension calls and the Java calls.
class Engine
# The default computational expense parameter.
DEFAULT_COST = 10
# The minimum cost supported by the algorithm.
MIN_COST = 4
# Maximum possible size of bcrypt() salts.
MAX_SALT_LENGTH = 16

# C-level routines which, if they don't get the right input, will crash the
# hell out of the Ruby process.
private_class_method :__bc_salt
private_class_method :__bc_crypt
if RUBY_PLATFORM != "java"
# C-level routines which, if they don't get the right input, will crash the
# hell out of the Ruby process.
private_class_method :__bc_salt
private_class_method :__bc_crypt
end

# Given a secret and a valid salt (see BCrypt::Engine.generate_salt) calculates
# a bcrypt() password hash.
def self.hash_secret(secret, salt)
if valid_secret?(secret)
if valid_salt?(salt)
__bc_crypt(secret.to_s, salt)
if RUBY_PLATFORM == "java"
Java.bcrypt_jruby.BCrypt.hashpw(secret.to_s, salt.to_s)
else
__bc_crypt(secret.to_s, salt)
end
else
raise Errors::InvalidSalt.new("invalid salt")
end
Expand All @@ -42,8 +56,16 @@ def self.hash_secret(secret, salt)

# Generates a random salt with a given computational cost.
def self.generate_salt(cost = DEFAULT_COST)
if cost.to_i > 0
__bc_salt(cost, OpenSSL::Random.random_bytes(MAX_SALT_LENGTH))
cost = cost.to_i
if cost > 0
if cost < MIN_COST
cost = MIN_COST
end
if RUBY_PLATFORM == "java"
Java.bcrypt_jruby.BCrypt.gensalt(cost)
else
__bc_salt(cost, OpenSSL::Random.random_bytes(MAX_SALT_LENGTH))
end
else
raise Errors::InvalidCost.new("cost must be numeric and > 0")
end
Expand Down

0 comments on commit 8f7acf4

Please sign in to comment.