Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Finish JRuby support.

Signed-off-by: Coda Hale <coda.hale@gmail.com>
  • Loading branch information...
commit 8f7acf49d55b45dbc448f40547d9087762263ddb 1 parent 1354343
@FooBarWidget FooBarWidget authored codahale committed
Showing with 78 additions and 22 deletions.
  1. +27 −6 Rakefile
  2. +18 −5 ext/extconf.rb
  3. +33 −11 lib/bcrypt.rb
View
33 Rakefile
@@ -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",
@@ -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
View
23 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
View
44 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.
@@ -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
@@ -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
Please sign in to comment.
Something went wrong with that request. Please try again.