class DevRandomPasswords::Generator

Constants

DIGITS
LOWERCASE_CHARS
NOT_READABLE_ERROR
REQUIREMENT_CONFLICT_ERROR
SPECIAL_CHARS
UPPERCASE_CHARS

Attributes

char_length[RW]
charset[RW]

Public Class Methods

new() click to toggle source
# File lib/dev-random-passwords.rb, line 14
def initialize
  @charset = LOWERCASE_CHARS + UPPERCASE_CHARS + DIGITS + SPECIAL_CHARS
  @char_length = 12
  @requirements = nil
  @hardware_random = false
end

Public Instance Methods

generate() click to toggle source
# File lib/dev-random-passwords.rb, line 116
def generate
  new_password = ""

  @char_length.times do
    rand_num = get_byte
    while rand_num >= @charset.length
      rand_num -= @charset.length
    end
    new_password += @charset[rand_num]
  end

  check_for_conflicts

  if requirements_met? new_password
    return new_password
  else
    return generate
  end

end
set_options(options={ 'lowercase' => true, 'uppercase' => true, 'digits' => true, 'special' => true, 'include' => nil, 'exclude' => nil, 'length' => 12, 'requirements' => nil}) click to toggle source
# File lib/dev-random-passwords.rb, line 21
def set_options(options={
  'lowercase' => true,
  'uppercase' => true,
  'digits' => true,
  'special' => true,
  'include' => nil,
  'exclude' => nil,
  'length' => 12,
  'requirements' => nil})

  new_set = ""

  if options['lowercase']
    new_set += LOWERCASE_CHARS
  end

  if options['uppercase']
    new_set += UPPERCASE_CHARS
  end

  if options['digits']
    new_set += DIGITS
  end

  if options['special']
    new_set += SPECIAL_CHARS
  end

  if new_set.empty?
    unless options['lowercase'] == false
      new_set = new_set + LOWERCASE_CHARS
    end
    unless options['uppercase'] == false
      new_set = new_set + UPPERCASE_CHARS
    end
    unless options['digits'] == false
      new_set = new_set + DIGITS
    end
    unless options['special'] == false
      new_set = new_set + SPECIAL_CHARS
    end
  end

  if options['include']
    if options['include'].respond_to? :each
      options['include'].each do |char|
        unless new_set.include? char
          new_set.insert(-1, char)
        end
      end
    elsif options['include'].respond_to? :split
      options['include'].split("").each do |char|
        unless new_set.include? char
          new_set.insert(-1, char)
        end
      end
    end
  end

  if options['exclude']
    if options['exclude'].respond_to? :each
      options['exclude'].each do |char|
        if new_set.include? char
          new_set = new_set.tr(char, '')
        end
      end
    elsif options['exclude'].respond_to? :split
      options['exclude'].split("").each do |char|
        if new_set.include? char
          new_set = new_set.tr(char, '')
        end
      end
    end
  end

  if new_set.empty?
    raise BAD_CHARACTER_SET_ERROR
  end

  @charset = new_set

  if options['length']
    if options['length'].respond_to? :to_i
      @char_length = options['length'].to_i
    end
  end

  if options['requirements']
    @requirements = options['requirements']
  end

  nil

end

Private Instance Methods

check_for_conflicts() click to toggle source
# File lib/dev-random-passwords.rb, line 255
def check_for_conflicts

  if @requirements
    if @requirements['uppercase']
      if (@charset.split("") & UPPERCASE_CHARS.split("")).empty?
        raise REQUIREMENT_CONFLICT_ERROR
      end
    end

    if @requirements['lowercase']
      if (@charset.split("") & LOWERCASE_CHARS.split("")).empty?
        raise REQUIREMENT_CONFLICT_ERROR
      end
    end

    if @requirements['digits']
      if (@charset.split("") & DIGITS.split("")).empty?
        raise REQUIREMENT_CONFLICT_ERROR
      end
    end

    if @requirements['special']
      if (@charset.split("") & SPECIAL_CHARS.split("")).empty?
        raise REQUIREMENT_CONFLICT_ERROR
      end
    end
  end

end
get_byte() click to toggle source
# File lib/dev-random-passwords.rb, line 139
def get_byte
  if @hardware_random == true
    hw_byte = read_byte_from_hw
    if hw_byte
      return hw_byte
    end
  end

  random_byte = read_byte_from_dev_random
  if random_byte
    return random_byte
  end

  random_byte = read_byte_from_dev_urandom
  if random_byte
    return random_byte
  else
    raise "Could not find a random number generator on your system"
  end
end
read_byte_from_dev_random() click to toggle source
# File lib/dev-random-passwords.rb, line 175
def read_byte_from_dev_random
  if File.exist?('/proc/sys/kernel/random/entropy_avail')
    if `cat /proc/sys/kernel/random/entropy_avail`.chomp.to_i < 64
      return read_byte_from_dev_urandom
    end
  end
  if File.exist?('/dev/random')
    if File.readable?('/dev/random')
      random_file = File.new('/dev/random', 'r')
      random_byte = random_file.read(1).ord
      random_file.close
      if random_byte
        return random_byte
      end
    else
      raise "/dev/random #{NOT_READABLE_ERROR}"
    end
  end
end
read_byte_from_dev_urandom() click to toggle source
# File lib/dev-random-passwords.rb, line 160
def read_byte_from_dev_urandom
  if File.exist?('/dev/urandom')
    if File.readable?('/dev/urandom')
      random_file = File.new('/dev/urandom', 'r')
      random_byte = random_file.read(1).ord
      random_file.close
      if random_byte
        return random_byte
      end
    else
      raise "/dev/urandom #{NOT_READABLE_ERROR}"
    end
  end
end
read_byte_from_hw() click to toggle source
# File lib/dev-random-passwords.rb, line 195
def read_byte_from_hw
  if File.exist?('/dev/hwrng')
    if File.readable?('/dev/hwrng')
      random_file = File.new('/dev/hwrng', 'r')
      random_byte = random_file.read(1).ord
      random_file.close
      if random_byte
        return random_byte
      end
    else
      raise "/dev/hwrng #{NOT_READABLE_ERROR}"
    end
  end

  if File.exist?('/dev/hwrandom')
    if File.readable?('/dev/hwrandom')
      random_file = File.new('/dev/hwrandom', 'r')
      random_byte = random_file.read(1).ord
      random_file.close
      if random_byte
        return random_byte
      end
    else
      raise "/dev/hwrandom #{NOT_READABLE_ERROR}"
    end
  end
end
requirements_met?(password) click to toggle source
# File lib/dev-random-passwords.rb, line 223
def requirements_met?(password)

  if @requirements
    if @requirements['uppercase']
      if (password.split("") & UPPERCASE_CHARS.split("")).empty?
        return false
      end
    end

    if @requirements['lowercase']
      if (password.split("") & LOWERCASE_CHARS.split("")).empty?
        return false
      end
    end

    if @requirements['digits']
      if (password.split("") & DIGITS.split("")).empty?
        return false
      end
    end

    if @requirements['special']
      if (password.split("") & SPECIAL_CHARS.split("")).empty?
        return false
      end
    end
  end

  return true

end