class DjangoHash
Attributes
hsh[R]
Public Class Methods
new(params)
click to toggle source
# File lib/pbkdf2_password_hasher/django_hash.rb, line 7 def initialize(params) @password = params[:password] @dklen = params[:dklen] || 32 @c = params[:c].to_i || 12_000 @hsh = params[:hash] @salt = params[:salt] @hash_f = OpenSSL::Digest.new('sha256') end
parse(str)
click to toggle source
Instanciate class using hash string
# File lib/pbkdf2_password_hasher/django_hash.rb, line 18 def self.parse(str) algo, c, salt, hsh = str.split('$') fail "sorry, don't know what to do with #{algo}" unless algo == 'pbkdf2_sha256' DjangoHash.new( :dklen => Base64.decode64(hsh).size, :c => c, :salt => salt, :hash => hsh ) end
Public Instance Methods
check_password(password)
click to toggle source
Check password against computed hash
# File lib/pbkdf2_password_hasher/django_hash.rb, line 35 def check_password(password) @password = password @hsh == get_hash end
get_hash()
click to toggle source
Compute hash
# File lib/pbkdf2_password_hasher/django_hash.rb, line 30 def get_hash (1..number_of_blocks).map(&block).reduce('', &:<<) end
Private Instance Methods
block()
click to toggle source
# File lib/pbkdf2_password_hasher/django_hash.rb, line 57 def block -> i do u = prf(@salt + [i].pack('N')) f = u 2.upto(@c) do |_i| u = prf(u) f = xor(f, u) end Base64.encode64(f[0..@dklen - 1]).chomp end end
number_of_blocks()
click to toggle source
# File lib/pbkdf2_password_hasher/django_hash.rb, line 42 def number_of_blocks (@dklen.to_f / @hash_f.size).ceil end
prf(data)
click to toggle source
Pseudo Random Function, as described in wikipedia
# File lib/pbkdf2_password_hasher/django_hash.rb, line 52 def prf(data) @hash_func ||= OpenSSL::Digest.new('sha256') OpenSSL::HMAC.digest(@hash_func, @password, data) end
xor(s1, s2)
click to toggle source
“string xor”
# File lib/pbkdf2_password_hasher/django_hash.rb, line 47 def xor(s1, s2) s1.bytes.zip((s2).bytes).map { |a, b| a ^ b }.pack('C*') end