Module: NdrSupport::Password

Extended by:
Password
Includes:
Constants
Included in:
Password
Defined in:
lib/ndr_support/password.rb,
lib/ndr_support/password/constants.rb

Overview

Contains logic for checking and generating secure passwords, in line with CESG guidelines.

Defined Under Namespace

Modules: Constants

Constant Summary

Constants included from Constants

Constants::COMMON_PASSWORDS, Constants::RFC1751_WORDS

Instance Method Summary collapse

Instance Method Details

#generate(number_of_words: 4, separator: ' ') ⇒ Object

Generates a random #valid? password, using the 2048-word RFC1751 dictionary. Optionally, specify ‘number_of_words` and/or `separator`.

NdrSupport::Password.generate #=> "sill quod okay phi"
NdrSupport::Password.generate #=> "dint dale pew wane"
NdrSupport::Password.generate #=> "rent jude ding gent"

NdrSupport::Password.generate(number_of_words: 6) #=> "dad bide thee glen road beam"

NdrSupport::Password.generate(separator: '-') #=> "jail-net-skim-cup"

Raises a RuntimeError if a strong enough password was not produced:

NdrSupport::Password.generate(number_of_words: 1) #=>
  RuntimeError: Failed to generate a #valid? password!


41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/ndr_support/password.rb', line 41

def generate(number_of_words: 4, separator: ' ')
  attempts = 0

  loop do
    words = Array.new(number_of_words) do
      RFC1751_WORDS[SecureRandom.random_number(RFC1751_WORDS.length)].downcase
    end

    phrase = words.join(separator)
    return phrase if valid?(phrase)

    attempts += 1
    raise 'Failed to generate a #valid? password!' if attempts > 10
  end
end

#valid?(string, word_list: []) ⇒ Boolean

Is the given ‘string` deemed a good password? An additional `word_list` can be provided; its entries add only minimally when considering the strength of `string`.

NdrSupport::Password.valid?('google password')    #=> false
NdrSupport::Password.valid?(SecureRandom.hex(12)) #=> true

Returns:

  • (Boolean)


18
19
20
21
22
23
# File 'lib/ndr_support/password.rb', line 18

def valid?(string, word_list: [])
  string = prepare_string(string.to_s.dup)
  slug   = slugify(strip_common_words(string, word_list))

  meets_requirements?(slug)
end