class EasyPassword

Adding a simple password generator and using it by default:

# Generate 10 random alphanumeric characters
EasyPassword.generator :random10 do
  SecureRandom.alphanumeric(10)
end

# Define the default generator
EasyPassword.default_generator = :random10

Adding a checker

# Implementing classic at least 1 lowercase, 1 upercase, 1 digit
EasyPassword.checker :aA1 do |password, all|
  list = { /\d/    => :digit_needed,
           /[A-Z]/ => :upercase_needed,
           /[a-z]/ => :lowercase_needed,
         }.lazy.map {|regex, failure| failure if password !~ regex }
               .reject(&:nil?)
  all ? list.to_a : list.first
end

# Looking for known bad passwords in a database (using Sequel)
Password.checker :hack_dictionary do |password, all|
  ! DB[:bad_passwords].first(:password => password).nil?
end

Creating password

password = EasyPassword.new
password = EasyPassword.new('foobar')

Checking for weakness

password.weakness

Constants

Digest
VERSION

Version

Public Class Methods

checker(name, &block) click to toggle source

DSL to ass a new password checker

@yieldparam [String] password plain text password @yieldparam [Boolean] all should all weakness be listed @yieldreturn [false, nil, []] if no weakness have been discovered @yieldreturn [true, Symbol, Array<Symbol>] name of weakness

# File lib/easy-password.rb, line 112
def self.checker(name, &block)
    @checkers[name] ||= block
end
default_checkers() click to toggle source

List of default checkers to use

# File lib/easy-password.rb, line 90
def self.default_checkers
    @default_checkers
end
default_checkers=(checkers) click to toggle source

Define the list of default checkers to use

@param [Array<Symbol>,nil] checkers list of checkers nickname, if nil

all available checkers will be used
# File lib/easy-password.rb, line 84
def self.default_checkers=(checkers)
    @default_checkers = checkers
end
default_generator() click to toggle source

Default generator

# File lib/easy-password.rb, line 74
def self.default_generator
    @default_generator
end
default_generator=(type) click to toggle source

Define the default generator to use

@param [Symbol] type Generator nickname

# File lib/easy-password.rb, line 68
def self.default_generator=(type)
    @default_generator = type
end
generate(type = self.default_generator) click to toggle source

Generate a plain text password string.

@param [Symbol] type Generator nickname @return [String]

# File lib/easy-password.rb, line 159
def self.generate(type = self.default_generator)
    if type.nil?
        raise ArgumentError, 'invalid generator type'
    end
        
    @generators[type]&.call() ||
        raise("requested generator '#{type}' doesn't exist")
end
generator(name, &block) click to toggle source

DSL to add a new password generator

@yieldparam [void] @yieldreturn [String] plain text password

# File lib/easy-password.rb, line 100
def self.generator(name, &block)
    @generators[name] = block
end
hide() click to toggle source

Is password value hidden when calling to_s

# File lib/easy-password.rb, line 53
def self.hide
    @hide
end
hide=(hide) click to toggle source

Control if password value is hidden when calling to_s

# File lib/easy-password.rb, line 59
def self.hide=(hide)
    @hide = hide
end
lmhash(password) click to toggle source

Create a LMHASH-hashed password

@param [String] password plain text password

@return [String] hashed password

# File lib/easy-password.rb, line 219
def self.lmhash(password)
    passwd = password[0..13].upcase
    passwd = passwd + "\000" * (14 - passwd.length)
    des = OpenSSL::Cipher::Cipher.new('des-ecb')
    des.encrypt
    [passwd[0..6], passwd[7..13]].collect { |key56|
        keybin = key56.unpack('B*')[0].scan(/.{7}/).collect {|k|
            k + (k.count('1') % 2 == 0 ? '1' : '0') }
        des.key = keybin.pack('B8' * 8)
        des.update('KGS!@#$%')
    }.join.unpack('C*').map { |b| '%02x' % b }.join
end
md5(password) click to toggle source

Create a MD5-hashed password

@param [String] password plain text password

@return [String] hashed password

# File lib/easy-password.rb, line 175
def self.md5(password)
    "{MD5}"    + [Digest::MD5.digest(password)   ].pack('m0')
end
new(password = EasyPassword::generate) click to toggle source

Create a new EasyPassword

# File lib/easy-password.rb, line 234
def initialize(password = EasyPassword::generate)
    @passwd = password.clone.freeze
end
ntlm(password) click to toggle source

Create an NTML-hashed password

@param [String] password plain text password

@return [String] hashed password

# File lib/easy-password.rb, line 208
def self.ntlm(password)
    Digest::MD4.hexdigest(password.encode("utf-16le"))
end
sha(password) click to toggle source

Create a SHA-hashed password

@param [String] password plain text password

@return [String] hashed password

# File lib/easy-password.rb, line 186
def self.sha(password)
    "{SHA}"    + [Digest::SHA1.digest(password)  ].pack('m0')
end
sha256(password) click to toggle source

Create a SHA256-hashed password

@param [String] password plain text password

@return [String] hashed password

# File lib/easy-password.rb, line 197
def self.sha256(password)
    "{sha256}" + [Digest::SHA256.digest(password)].pack('m0')
end
weakness(password, *checkers, all: true) click to toggle source

Check for weakness

@param [String, EasyPassword] password @param [Symbol] checkers @param [Boolean] all

@raise [KeyError] if a requested checker is not defined

@return [Hash{Symbol=>Array<Symbol>}]

# File lib/easy-password.rb, line 127
def self.weakness(password, *checkers, all: true)
    return nil              if @checkers.empty?       
    password = password.raw if password.kind_of?(EasyPassword)

    checkers = self.default_checkers if checkers.empty?
    list     = if checkers.nil? || checkers.empty?
               then @checkers.lazy
               else checkers.lazy.map {|n| [n, @checkers.fetch(n)] }
               end
    list     = list.map {|name, checker|
        case r = checker.call(password, all: all)
        when Array      then [ name, r        ] unless r.empty?
        when Symbol     then [ name, [ r ]    ]
        when true       then [ name, [ name ] ]
        when nil, false
        else raise ArgumentError, 'unsupported checker return value'
        end
    }.reject(&:nil?)

    list = if all
           then Hash[list.to_a]
           else Hash[*list.first].transform_values {|v| v[0,1] }
           end
    list unless list.empty?
end

Public Instance Methods

lmhash() click to toggle source

Get the LMHASH-hashed password

@return [String] hashed password

# File lib/easy-password.rb, line 287
def lmhash
    self.class.lmhash(@passwd)
end
md5() click to toggle source

Get the MD5-hashed password

@return [String] hashed password

# File lib/easy-password.rb, line 269
def md5
    self.class.md5(@passwd)
end
ntlm() click to toggle source

Get the NTLM-hashed password

@return [String] hashed password

# File lib/easy-password.rb, line 278
def ntlm
    self.class.ntlm(@passwd)
end
raw() click to toggle source

Get the plain text password

@return [String] plain text password

# File lib/easy-password.rb, line 242
def raw
    @passwd
end
sha() click to toggle source

Get the SHA256-hashed password

@return [String] hashed password

# File lib/easy-password.rb, line 251
def sha
    self.class.sha(@passwd)
end
sha256() click to toggle source

Get the SHA256-hashed password

@return [String] hashed password

# File lib/easy-password.rb, line 260
def sha256
    self.class.sha256(@passwd)
end
to_s() click to toggle source

Display password. The behavior is controlled by Password.hide, so either the plain text password will be displayed or ********

@return [String]

# File lib/easy-password.rb, line 298
def to_s
    self.class.hide != true ? "********" : self.raw
end
weakness(*checkers, all: true) click to toggle source

Check for weakness

@param [Symbol] checkers @param [Boolean] all

@raise [KeyError] if a requested checker is not defined

@return [Hash{Symbol=>Array<Symbol>}]

# File lib/easy-password.rb, line 312
def weakness(*checkers, all: true)
    self.class.weakness(@passwd, *checkers, all: all)
end