Class: EasyPassword
- Inherits:
-
Object
- Object
- EasyPassword
- Defined in:
- lib/easy-password.rb,
lib/easy-password/md4.rb,
lib/easy-password/version.rb
Overview
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
Constant Summary collapse
- Digest =
OpenSSL::Digest
- VERSION =
Version
'0.1.2'
Class Method Summary collapse
-
.checker(name) {|password, all| ... } ⇒ Object
DSL to ass a new password checker.
-
.default_checkers ⇒ Object
List of default checkers to use.
-
.default_checkers=(checkers) ⇒ Object
Define the list of default checkers to use.
-
.default_generator ⇒ Object
Default generator.
-
.default_generator=(type) ⇒ Object
Define the default generator to use.
-
.generate(type = self.default_generator) ⇒ String
Generate a plain text password string.
-
.generator(name) {|| ... } ⇒ Object
DSL to add a new password generator.
-
.hide ⇒ Object
Is password value hidden when calling #to_s.
-
.hide=(hide) ⇒ Object
Control if password value is hidden when calling #to_s.
-
.lmhash(password) ⇒ String
Create a LMHASH-hashed password.
-
.md5(password) ⇒ String
Create a MD5-hashed password.
-
.ntlm(password) ⇒ String
Create an NTML-hashed password.
-
.sha(password) ⇒ String
Create a SHA-hashed password.
-
.sha256(password) ⇒ String
Create a SHA256-hashed password.
-
.weakness(password, *checkers, all: true) ⇒ Hash{Symbol=>Array<Symbol>}
Check for weakness.
Instance Method Summary collapse
-
#==(other) ⇒ Object
Override equality.
-
#initialize(password = EasyPassword::generate) ⇒ EasyPassword
constructor
Create a new EasyPassword.
-
#lmhash ⇒ String
Get the LMHASH-hashed password.
-
#md5 ⇒ String
Get the MD5-hashed password.
-
#ntlm ⇒ String
Get the NTLM-hashed password.
-
#raw ⇒ String
Get the plain text password.
-
#sha ⇒ String
Get the SHA256-hashed password.
-
#sha256 ⇒ String
Get the SHA256-hashed password.
-
#to_s ⇒ String
Display password.
-
#weakness(*checkers, all: true) ⇒ Hash{Symbol=>Array<Symbol>}
Check for weakness.
Constructor Details
#initialize(password = EasyPassword::generate) ⇒ EasyPassword
Create a new EasyPassword
238 239 240 |
# File 'lib/easy-password.rb', line 238 def initialize(password = EasyPassword::generate) @passwd = password.clone.freeze end |
Class Method Details
.checker(name) {|password, all| ... } ⇒ Object
DSL to ass a new password checker
113 114 115 |
# File 'lib/easy-password.rb', line 113 def self.checker(name, &block) @checkers[name] ||= block end |
.default_checkers ⇒ Object
List of default checkers to use
91 92 93 |
# File 'lib/easy-password.rb', line 91 def self.default_checkers @default_checkers end |
.default_checkers=(checkers) ⇒ Object
Define the list of default checkers to use
85 86 87 |
# File 'lib/easy-password.rb', line 85 def self.default_checkers=(checkers) @default_checkers = checkers end |
.default_generator ⇒ Object
Default generator
75 76 77 |
# File 'lib/easy-password.rb', line 75 def self.default_generator @default_generator end |
.default_generator=(type) ⇒ Object
Define the default generator to use
69 70 71 |
# File 'lib/easy-password.rb', line 69 def self.default_generator=(type) @default_generator = type end |
.generate(type = self.default_generator) ⇒ String
Generate a plain text password string.
160 161 162 163 164 165 166 167 |
# File 'lib/easy-password.rb', line 160 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) {|| ... } ⇒ Object
DSL to add a new password generator
101 102 103 |
# File 'lib/easy-password.rb', line 101 def self.generator(name, &block) @generators[name] = block end |
.hide ⇒ Object
Is password value hidden when calling #to_s
54 55 56 |
# File 'lib/easy-password.rb', line 54 def self.hide @hide end |
.hide=(hide) ⇒ Object
Control if password value is hidden when calling #to_s
60 61 62 |
# File 'lib/easy-password.rb', line 60 def self.hide=(hide) @hide = hide end |
.lmhash(password) ⇒ String
Create a LMHASH-hashed password
223 224 225 226 227 228 229 230 231 232 233 234 |
# File 'lib/easy-password.rb', line 223 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) ⇒ String
Create a MD5-hashed password
176 177 178 |
# File 'lib/easy-password.rb', line 176 def self.md5(password) "{MD5}" + [Digest::MD5.digest(password) ].pack('m0') end |
.ntlm(password) ⇒ String
Create an NTML-hashed password
209 210 211 212 213 214 |
# File 'lib/easy-password.rb', line 209 def self.ntlm(password) # New version of OpenSSL doesn't provide MD4 anymore # Digest::MD4.hexdigest(password.encode("utf-16le")) self.digest_md4(password.encode("utf-16le").force_encoding('BINARY')) .unpack1('H*') end |
.sha(password) ⇒ String
Create a SHA-hashed password
187 188 189 |
# File 'lib/easy-password.rb', line 187 def self.sha(password) "{SHA}" + [Digest::SHA1.digest(password) ].pack('m0') end |
.sha256(password) ⇒ String
Create a SHA256-hashed password
198 199 200 |
# File 'lib/easy-password.rb', line 198 def self.sha256(password) "{sha256}" + [Digest::SHA256.digest(password)].pack('m0') end |
.weakness(password, *checkers, all: true) ⇒ Hash{Symbol=>Array<Symbol>}
Check for weakness
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
# File 'lib/easy-password.rb', line 128 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 |
Instance Method Details
#==(other) ⇒ Object
Override equality
244 245 246 |
# File 'lib/easy-password.rb', line 244 def ==(other) !other.nil? && other.is_a?(EasyPassword) && self.raw == other.raw end |
#lmhash ⇒ String
Get the LMHASH-hashed password
297 298 299 |
# File 'lib/easy-password.rb', line 297 def lmhash self.class.lmhash(@passwd) end |
#md5 ⇒ String
Get the MD5-hashed password
279 280 281 |
# File 'lib/easy-password.rb', line 279 def md5 self.class.md5(@passwd) end |
#ntlm ⇒ String
Get the NTLM-hashed password
288 289 290 |
# File 'lib/easy-password.rb', line 288 def ntlm self.class.ntlm(@passwd) end |
#raw ⇒ String
Get the plain text password
252 253 254 |
# File 'lib/easy-password.rb', line 252 def raw @passwd end |
#sha ⇒ String
Get the SHA256-hashed password
261 262 263 |
# File 'lib/easy-password.rb', line 261 def sha self.class.sha(@passwd) end |
#sha256 ⇒ String
Get the SHA256-hashed password
270 271 272 |
# File 'lib/easy-password.rb', line 270 def sha256 self.class.sha256(@passwd) end |
#to_s ⇒ String
Display password. The behavior is controlled by Password.hide, so either the plain text password will be displayed or ********
308 309 310 |
# File 'lib/easy-password.rb', line 308 def to_s self.class.hide != true ? "********" : self.raw end |
#weakness(*checkers, all: true) ⇒ Hash{Symbol=>Array<Symbol>}
Check for weakness
322 323 324 |
# File 'lib/easy-password.rb', line 322 def weakness(*checkers, all: true) self.class.weakness(@passwd, *checkers, all: all) end |