class RubyDrupalHash

RubyDrupalHash.verify(“password1234”, “$S$DeIZ1KTE.VzRvudZ5.xgOakipuMFrVyPmRdWTjAdYieWj27NMglI”)

Constants

DRUPAL_HASH_COUNT
DRUPAL_HASH_LENGTH
DRUPAL_MAX_HASH_COUNT
DRUPAL_MIN_HASH_COUNT
HASH
ITOA64

Public Class Methods

is_drupal_hash?(hashed_password) click to toggle source
# File lib/ruby_drupal_hash.rb, line 29
def self.is_drupal_hash?(hashed_password)
  hashed_password and (hashed_password[0..3] == 'U$S$' || hashed_password[0..2] == '$S$')
end
verify(password, hashed_password) click to toggle source
# File lib/ruby_drupal_hash.rb, line 33
def self.verify(password, hashed_password)
  return false if password.nil? or hashed_password.nil?
  return false if not is_drupal_hash?(hashed_password)

  # Known as an 'upgraded' Drupal hash
  if hashed_password[0..1] == 'U$'
    hashed_password = hashed_password[1..-1]
    password = Digest::MD5.new().hexdigest(password)
  end
  
  setting = hashed_password[0..11]
  if setting[0] != '$' or setting[2] != '$'
    # Wrong hash format
    return false
  end
      
  count_log2 = ITOA64.index(setting[3])
  
  if count_log2 < DRUPAL_MIN_HASH_COUNT or count_log2 > DRUPAL_MAX_HASH_COUNT
    return false
  end

  salt = setting[4..4+7]
  
  if salt.length != 8
    return false
  end
  
  count = 2 ** count_log2
     
  pass_hash = HASH.digest(salt + password)

  1.upto(count) do |i|
    pass_hash = HASH.digest(pass_hash + password)
  end

  hash_length = pass_hash.length

  output = setting + password_base64_encode(pass_hash, hash_length)

  if output.length != 98
    return false
  end

  return output[0..(DRUPAL_HASH_LENGTH-1)] == hashed_password      
end

Private Class Methods

password_base64_encode(to_encode, count) click to toggle source
# File lib/ruby_drupal_hash.rb, line 81
def self.password_base64_encode(to_encode, count)
  output = ''
  i = 0
  while true
    value = (to_encode[i]).ord
        
    i += 1
        
    output = output + ITOA64[value & 0x3f]
    if i < count
      value |= (to_encode[i].ord) << 8
    end

    output = output + ITOA64[(value >> 6) & 0x3f]

    if i >= count
      break
    end

    i += 1

    if i < count
      value |= (to_encode[i].ord) << 16
    end
        
    output = output + ITOA64[(value >> 12) & 0x3f]

    if i >= count
      break
    end
    
    i += 1
    
    output = output + ITOA64[(value >> 18) & 0x3f]
        
    if i >= count
      break
    end
    
  end
  return output
end