Commit 5c63bf7112f3bec6a2f14cd3645f265667e9726e
FFI Wrapper to run bcrypt-ruby on Maglev
* compiles to shared object using a custom Makefile * loads bcrypt_engine which wraps the shared object using FFI to offer the same interface as the plain C extensionTim Felgentreff committed on 1/9/2011, 1:58:18 PM
Parent: eab1c727ed44365d4803bb224d056f48ebec905c
Files changed
ext/mri/extconf.rb | changed |
lib/bcrypt.rb | changed |
lib/bcrypt_engine.rb | added |
ext/mri/extconf.rb | ||
---|---|---|
@@ -8,8 +8,31 @@ | ||
8 | 8 | f.puts "install:" |
9 | 9 | f.puts "\t@true" |
10 | 10 | end |
11 | 11 | exit 0 |
12 | +elsif RUBY_ENGINE == "maglev" | |
13 | + # Maglev doesn't support C extensions, fall back to compiling an FFI usable | |
14 | + # library | |
15 | + File.open('Makefile', 'w') do |f| | |
16 | + f.puts <<-MAKEFILE | |
17 | +CFLAGS = -fPIC | |
18 | +OBJS = bcrypt.o blowfish.o | |
19 | +DLIB = bcrypt_ext.so | |
20 | +OS ?= $(strip $(shell uname -s | tr '[:upper:]' '[:lower:]')) | |
21 | +ifeq ($(OS),darwin) | |
22 | + DLIB = bcrypt_ext.dylib | |
23 | + CFLAGS += -dynamiclib | |
24 | +endif | |
25 | + | |
26 | +all: $(OBJS) | |
27 | + cc -shared -o $(DLIB) $(OBJS) | |
28 | +install: | |
29 | + install $(DLIB) "../../lib/" | |
30 | +clean: | |
31 | + $(RM) $(OBJS) bcrypt_ext.so | |
32 | + MAKEFILE | |
33 | + end | |
34 | + exit 0 | |
12 | 35 | else |
13 | 36 | require "mkmf" |
14 | 37 | dir_config("bcrypt_ext") |
15 | 38 | CONFIG['CC'] << " -Wall " |
lib/bcrypt.rb | ||
---|---|---|
@@ -5,9 +5,13 @@ | ||
5 | 5 | else |
6 | 6 | require "openssl" |
7 | 7 | end |
8 | 8 | |
9 | -require 'bcrypt_ext' | |
9 | +if RUBY_ENGINE == "maglev" | |
10 | + require 'bcrypt_engine' | |
11 | +else | |
12 | + require 'bcrypt_ext' | |
13 | +end | |
10 | 14 | |
11 | 15 | # A Ruby library implementing OpenBSD's bcrypt()/crypt_blowfish algorithm for |
12 | 16 | # hashing passwords. |
13 | 17 | module BCrypt |
lib/bcrypt_engine.rb | ||
---|---|---|
@@ -1,0 +1,34 @@ | ||
1 | +require 'ffi' | |
2 | + | |
3 | +module BCrypt | |
4 | + class Engine | |
5 | + extend FFI::Library | |
6 | + | |
7 | + BCRYPT_MAXSALT = 16 | |
8 | + BCRYPT_SALT_OUTPUT_SIZE = 7 + (BCRYPT_MAXSALT * 4 + 2) / 3 + 1 | |
9 | + BCRYPT_OUTPUT_SIZE = 128 | |
10 | + | |
11 | + ffi_lib File.expand_path("../bcrypt_ext", __FILE__) | |
12 | + | |
13 | + attach_function :ruby_bcrypt, [:buffer_out, :string, :string], :string | |
14 | + attach_function :ruby_bcrypt_gensalt, [:buffer_out, :uint8, :pointer], :string | |
15 | + | |
16 | + def self.__bc_salt(cost, seed) | |
17 | + buffer_out = FFI::Buffer.alloc_out(BCRYPT_SALT_OUTPUT_SIZE, 1) | |
18 | + seed_ptr = FFI::MemoryPointer.new(:uint8, BCRYPT_MAXSALT) | |
19 | + seed.bytes.to_a.each_with_index { |b, i| seed_ptr.int8_put(i, b) } | |
20 | + out = ruby_bcrypt_gensalt(buffer_out, cost, seed_ptr) | |
21 | + seed_ptr.free | |
22 | + buffer_out.free | |
23 | + out || "" | |
24 | + end | |
25 | + | |
26 | + def self.__bc_crypt(key, salt, cost) | |
27 | + buffer_out = FFI::Buffer.alloc_out(BCRYPT_OUTPUT_SIZE, 1) | |
28 | + out = ruby_bcrypt(buffer_out, key || "", salt) | |
29 | + buffer_out.free | |
30 | + out && out.any? ? out : nil | |
31 | + end | |
32 | + end | |
33 | +end | |
34 | + |
Built with git-ssb-web