Module: Capsium::Reactor::Htpasswd::Md5Crypt
- Defined in:
- lib/capsium/reactor/htpasswd.rb,
sig/capsium/reactor/htpasswd.rbs
Overview
md5-crypt as deployed by Apache htpasswd, OpenSSL and glibc.
Constant Summary collapse
- ITOA64 =
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"- DIGEST_GROUPS =
[[0, 6, 12], [1, 7, 13], [2, 8, 14], [3, 9, 15], [4, 10, 5]].freeze
Class Method Summary collapse
- .digest(password, salt, magic) ⇒ String
- .initial_digest(password, salt, magic) ⇒ String
- .stretch_digest(iteration, password, salt, final) ⇒ String
-
.to64(final) ⇒ String
The custom base-64 of md5-crypt: digest triples permuted, first index to the high bits, 22 characters total.
- .verify(hash, password) ⇒ Boolean
Class Method Details
.digest(password, salt, magic) ⇒ String
35 36 37 38 39 40 41 |
# File 'lib/capsium/reactor/htpasswd.rb', line 35 def self.digest(password, salt, magic) final = initial_digest(password, salt, magic) 1000.times do |i| final = stretch_digest(i, password, salt, final) end "#{magic}#{salt}$#{to64(final)}" end |
.initial_digest(password, salt, magic) ⇒ String
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/capsium/reactor/htpasswd.rb', line 43 def self.initial_digest(password, salt, magic) inner = Digest::MD5.digest(password + salt + password) context = Digest::MD5.new context << password << magic << salt length = password.length while length.positive? context << inner[0, [16, length].min] length -= 16 end length = password.length while length.positive? context << (length.odd? ? "\0" : password[0]) length >>= 1 end context.digest end |
.stretch_digest(iteration, password, salt, final) ⇒ String
60 61 62 63 64 65 66 67 |
# File 'lib/capsium/reactor/htpasswd.rb', line 60 def self.stretch_digest(iteration, password, salt, final) context = Digest::MD5.new context << (iteration.odd? ? password : final) context << salt unless (iteration % 3).zero? context << password unless (iteration % 7).zero? context << (iteration.odd? ? final : password) context.digest end |
.to64(final) ⇒ String
The custom base-64 of md5-crypt: digest triples permuted, first index to the high bits, 22 characters total.
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/capsium/reactor/htpasswd.rb', line 71 def self.to64(final) encoded = +"" DIGEST_GROUPS.each do |a, b, c| value = final[c].ord | (final[b].ord << 8) | (final[a].ord << 16) 4.times do encoded << ITOA64[value & 0x3f] value >>= 6 end end value = final[11].ord 2.times do encoded << ITOA64[value & 0x3f] value >>= 6 end encoded end |
.verify(hash, password) ⇒ Boolean
28 29 30 31 32 33 |
# File 'lib/capsium/reactor/htpasswd.rb', line 28 def self.verify(hash, password) _prefix, magic, salt, = hash.split("$", 4) return false if salt.nil? || salt.empty? Reactor.secure_compare(digest(password, salt, "$#{magic}$"), hash) end |