1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
|
require 'minitest/autorun'
require 'minitest/unit'
require 'test_helper'
# bcrypt_pbkdf in ruby
require 'openssl'
BCRYPT_BLOCKS = 8
BCRYPT_HASHSIZE = BCRYPT_BLOCKS * 4
def bcrypt_pbkdf(password, salt, keylen, rounds)
stride = (keylen + BCRYPT_HASHSIZE - 1) / BCRYPT_HASHSIZE
amt = (keylen + stride - 1) / stride
sha2pass = OpenSSL::Digest::SHA512.new(password).digest
#puts "[RB] sha2pass:#{sha2pass.inspect} #{sha2pass.size}"
remlen = keylen
countsalt = salt + "\x00"*4
saltlen = salt.size
key = "\x00"*keylen
# generate key in BCRYPT_HASHSIZE pieces
count = 1
while remlen > 0
countsalt[saltlen + 0] = ((count >> 24) & 0xff).chr
countsalt[saltlen + 1] = ((count >> 16) & 0xff).chr
countsalt[saltlen + 2] = ((count >> 8) & 0xff).chr
countsalt[saltlen + 3] = (count & 0xff).chr
#puts "[RC] countsalt: #{countsalt.inspect} len:#{countsalt.size}"
sha2salt = OpenSSL::Digest::SHA512.new(countsalt).digest
tmpout = BCryptPbkdf::Engine::__bc_crypt_hash(sha2pass, sha2salt)
out = tmpout.clone
#puts "[RB] out: #{out.inspect} keylen:#{remlen} count:#{count}"
(1...rounds).each do |i|
sha2salt = OpenSSL::Digest::SHA512.new(tmpout).digest
tmpout = BCryptPbkdf::Engine::__bc_crypt_hash(sha2pass, sha2salt)
out.bytes.each_with_index {|o,j| out.setbyte(j,o ^ tmpout[j].ord) }
end
amt = [amt, remlen].min
(0...amt).each do |i|
dest = i * stride + (count - 1)
key[dest] = out[i] if (dest < keylen)
end
remlen -= amt
count += 1
end
key
end
class TestExt < Minitest::Unit::TestCase
def test_table
assert_equal table, table.map{ |p,s,l,r| [p,s,l,r,BCryptPbkdf::Engine::__bc_crypt_pbkdf(p,s,l,r).bytes] }
end
def test_ruby_and_native_returns_the_same
table.each do |p,s,l,r|
assert_equal bcrypt_pbkdf(p,s,l,r), BCryptPbkdf::Engine::__bc_crypt_pbkdf(p,s,l,r)
assert_equal bcrypt_pbkdf(p,s,l,r), BCryptPbkdf::key(p,s,l,r)
end
end
def table
[
["pass2", "salt2", 12, 2, [214, 14, 48, 162, 131, 206, 121, 176, 50, 104, 231, 252]],
["\u0000\u0001foo", "\u0001\u0002fooo3", 14, 5, [46, 189, 32, 185, 94, 85, 232, 10, 84, 26, 44, 161, 49, 126]],
["doozoasd", "fooo$AS!", 14, 22, [57, 62, 50, 107, 70, 155, 65, 5, 129, 211, 189, 169, 188, 65]]
]
end
end
|