Class | HTAuth::Md5 |
In: |
lib/htauth/md5.rb
|
Parent: | Algorithm |
an implementation of the MD5 based encoding algorithm as used in the apache htpasswd -m option
DIGEST_LENGTH | = | 16 |
# File lib/htauth/md5.rb, line 12 12: def initialize(params = {}) 13: @salt = params['salt'] || params[:salt] || gen_salt 14: end
this algorigthm pulled straight from apr_md5_encode() and converted to ruby syntax
# File lib/htauth/md5.rb, line 21 21: def encode(password) 22: primary = ::Digest::MD5.new 23: primary << password 24: primary << prefix 25: primary << @salt 26: 27: md5_t = ::Digest::MD5.digest("#{password}#{@salt}#{password}") 28: 29: l = password.length 30: while l > 0 do 31: slice_size = ( l > DIGEST_LENGTH ) ? DIGEST_LENGTH : l 32: primary << md5_t[0, slice_size] 33: l -= DIGEST_LENGTH 34: end 35: 36: # weirdness 37: l = password.length 38: while l != 0 39: case (l & 1) 40: when 1 41: primary << 0.chr 42: when 0 43: primary << password[0,1] 44: end 45: l >>= 1 46: end 47: 48: pd = primary.digest 49: 50: encoded_password = "#{prefix}#{@salt}$" 51: 52: # apr_md5_encode has this comment about a 60Mhz Pentium above this loop. 53: 1000.times do |x| 54: ctx = ::Digest::MD5.new 55: ctx << (( ( x & 1 ) == 1 ) ? password : pd[0,DIGEST_LENGTH]) 56: (ctx << @salt) unless ( x % 3 ) == 0 57: (ctx << password) unless ( x % 7 ) == 0 58: ctx << (( ( x & 1 ) == 0 ) ? password : pd[0,DIGEST_LENGTH]) 59: pd = ctx.digest 60: end 61: 62: 63: l = (pd[ 0]<<16) | (pd[ 6]<<8) | pd[12] 64: encoded_password << to_64(l, 4) 65: 66: l = (pd[ 1]<<16) | (pd[ 7]<<8) | pd[13] 67: encoded_password << to_64(l, 4) 68: 69: l = (pd[ 2]<<16) | (pd[ 8]<<8) | pd[14] 70: encoded_password << to_64(l, 4) 71: 72: l = (pd[ 3]<<16) | (pd[ 9]<<8) | pd[15] 73: encoded_password << to_64(l, 4) 74: 75: l = (pd[ 4]<<16) | (pd[10]<<8) | pd[ 5] 76: encoded_password << to_64(l, 4) 77: encoded_password << to_64(pd[11],2) 78: 79: return encoded_password 80: end