Skip to content

Instantly share code, notes, and snippets.

@antifuchs
Created September 30, 2013 18:16
Show Gist options
  • Save antifuchs/6767842 to your computer and use it in GitHub Desktop.
Save antifuchs/6767842 to your computer and use it in GitHub Desktop.
#!/usr/bin/env ruby
require 'optparse'
def exp_notation(n)
Math.log10(n).floor
end
def main
options = {}
optparse = OptionParser.new do |opts|
opts.banner = <<-EOB
Usage: #{0} [options] [number of words]
Generate a random passphrase from words in a dictionary.
EOB
opts.on('-v', "--verbose", "Output the number of combinations from which this password was picked") {
options[:verbose] = true
}
opts.on('-l', '--min-length=LENGTH', 'Set the minimum length for a constituent word (default: 3)') { |length|
options[:min] = length.to_i
}
opts.on('-u', '--max-length=LENGTH', 'Set the maximum length for a constituent word (default: 9)') { |length|
options[:max] = length.to_i
}
opts.on('-f', '--dictionary=DICT', 'Dictionary file to use (default: /usr/share/dict/words)') { |dict|
options[:dict] = dict
}
opts.on('-x', '--exclude-easy-typos', 'Exclude repeated chars at word boundaries') {
options[:exclude_duplicates_at_boundaries] = true
}
opts.on('-X', '--exclude-dupes-inside', 'Exclude repeated chars inside words') {
options[:exclude_duplicates] = true
}
opts.on('-h', '--help', 'This help') {
puts opts
exit(1)
}
end
optparse.parse!
n=(ARGV[0] || 4).to_i
min = options[:min] || 3
max = options[:max] || 9
dict = options[:dict] || '/usr/share/dict/words'
lines = File.open(dict).readlines.map {|line| line.chomp.downcase }.uniq.select {|word|
word.length >= min && word.length <= max && (!options[:exclude_duplicates] || !word.match(/([a-z])\1/))
}
words = []
last_word = ''
n.times do
word = lines[rand(lines.length)]
if options[:exclude_duplicates_at_boundaries] && last_word[-1] == word.first
continue
end
words << word
last_word = word
end
passphrase = words.join(' ').downcase
print passphrase
if options[:verbose]
puts " (10e#{exp_notation(27 ** passphrase.length)}c 10e#{exp_notation(lines.length ** words.length)}w)"
else
puts
end
end
main if $0 == __FILE__
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment