Module: Philiprehberger::Password::Strength
- Defined in:
- lib/philiprehberger/password/strength.rb
Constant Summary collapse
- LABELS =
{ 0 => :terrible, 1 => :weak, 2 => :fair, 3 => :strong, 4 => :excellent }.freeze
- MIN_RECOMMENDED_LENGTH =
Length below which the feedback advises adding characters.
12
Class Method Summary collapse
- .compute(password) ⇒ Object
- .entropy(password) ⇒ Object
-
.feedback(password, score) ⇒ Object
Build an actionable list of suggestions for improving a password.
Class Method Details
.compute(password) ⇒ Object
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/philiprehberger/password/strength.rb', line 17 def self.compute(password) pwd = password.to_s return { score: 0, label: :terrible, entropy: 0.0, feedback: feedback(pwd, 0) } if pwd.empty? ent = entropy(pwd) s = if ent < 28 0 elsif ent < 36 1 elsif ent < 60 2 elsif ent < 80 3 else 4 end { score: s, label: LABELS[s], entropy: ent.round(2), feedback: feedback(pwd, s) } end |
.entropy(password) ⇒ Object
38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/philiprehberger/password/strength.rb', line 38 def self.entropy(password) pwd = password.to_s return 0.0 if pwd.empty? pool = 0 pool += 26 if pwd.match?(/[a-z]/) pool += 26 if pwd.match?(/[A-Z]/) pool += 10 if pwd.match?(/\d/) pool += 33 if pwd.match?(/[^a-zA-Z\d]/) pwd.length * Math.log2([pool, 1].max) end |
.feedback(password, score) ⇒ Object
Build an actionable list of suggestions for improving a password. Returns an empty array for passwords that already score "strong" (3) or "excellent" (4).
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/philiprehberger/password/strength.rb', line 54 def self.feedback(password, score) return [] if score >= 3 pwd = password.to_s tips = [] tips << 'Avoid using a common password' if CommonPasswords.include?(pwd.downcase) tips << "Use at least #{MIN_RECOMMENDED_LENGTH} characters" if pwd.length < MIN_RECOMMENDED_LENGTH missing = missing_classes(pwd) tips << "Add #{to_sentence(missing)}" unless missing.empty? tips.concat(pattern_tips(pwd)) tips.uniq end |