2019-05-02 17:17:27 -05:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2013-03-06 06:12:16 -06:00
|
|
|
# Note: the pbkdf2 gem is bust on 2.0, the logic is so simple I am not sure it makes sense to have this in a gem atm (Sam)
|
|
|
|
#
|
|
|
|
# Also PBKDF2 monkey patches string ... don't like that at all
|
|
|
|
#
|
2013-07-22 20:36:01 -05:00
|
|
|
# Happy to move back to PBKDF2 ruby gem provided:
|
2013-03-06 06:12:16 -06:00
|
|
|
#
|
|
|
|
# 1. It works on Ruby 2.0
|
2013-07-22 20:36:01 -05:00
|
|
|
# 2. It works on 1.9.3
|
2013-03-06 06:12:16 -06:00
|
|
|
# 3. It does not monkey patch string
|
|
|
|
|
|
|
|
require 'openssl'
|
2013-03-08 07:54:40 -06:00
|
|
|
require 'xor'
|
2013-03-06 06:12:16 -06:00
|
|
|
|
|
|
|
class Pbkdf2
|
|
|
|
|
2013-07-22 20:36:01 -05:00
|
|
|
def self.hash_password(password, salt, iterations, algorithm = "sha256")
|
|
|
|
|
2014-01-20 11:33:40 -06:00
|
|
|
h = OpenSSL::Digest.new(algorithm)
|
2013-07-22 20:36:01 -05:00
|
|
|
|
2013-03-06 06:12:16 -06:00
|
|
|
u = ret = prf(h, password, salt + [1].pack("N"))
|
|
|
|
|
2013-07-22 20:36:01 -05:00
|
|
|
2.upto(iterations) do
|
2013-03-06 06:12:16 -06:00
|
|
|
u = prf(h, password, u)
|
2013-07-22 20:36:01 -05:00
|
|
|
ret.xor!(u)
|
2013-03-06 06:12:16 -06:00
|
|
|
end
|
|
|
|
|
|
|
|
ret.bytes.map { |b| ("0" + b.to_s(16))[-2..-1] }.join("")
|
|
|
|
end
|
|
|
|
|
2013-07-22 20:36:01 -05:00
|
|
|
protected
|
2013-03-06 06:12:16 -06:00
|
|
|
|
2013-03-08 07:54:40 -06:00
|
|
|
# fallback xor in case we need it for jruby ... way slower
|
2013-03-06 06:12:16 -06:00
|
|
|
def self.xor(x, y)
|
2018-02-25 17:25:58 -06:00
|
|
|
x.bytes.zip(y.bytes).map { |a, b| a ^ b }.pack('c*')
|
2013-03-06 06:12:16 -06:00
|
|
|
end
|
|
|
|
|
|
|
|
def self.prf(hash_function, password, data)
|
|
|
|
OpenSSL::HMAC.digest(hash_function, password, data)
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|