DZone Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

Snippets has posted 5883 posts at DZone. View Full User Profile

Generate Memorable Passphrases

10.28.2011
| 2724 views |
  • submit to reddit
        This snippet is a Ruby script to generate plain English passphrases of a specified length. Inspired by the XKCD "correct horse battery staple" strip.

#!/usr/bin/env ruby

USAGE = <<EOF
makepass.rb: Generate a passphrase with lowercase words

Usage:

  $ makepass.rb <length>

This script generates a plain-English passphrase of at least the given length
(in characters), using random words from /usr/share/dict/words. Only lowercase
letters a-z will be included in the output, making passphrases relatively easy
to type (though usually nonsensical).

Examples:

  $ ./makepass.rb 12
  hive frighten

  $ ./makepass.rb 24
  moppet castigator harvesters

  $ ./makepass.rb 32
  munificent icebound raymond clorets

A 32-character passphrase has about 120 bits of entropy, which is overkill for
most purposes. A 24-character passphrase clocks in at about 90 bits of entropy, 
suitable for most high-security applications like root passwords or financial
records. You might want to use a password checker to verify the strength of
your passphrase after generating one that you like:

  http://rumkin.com/tools/password/passchk.php

Inspired by http://xkcd.com/936/
EOF

DICT_PATH = '/usr/share/dict/words'
DICT_LINES = `wc -l #{DICT_PATH}`.split.first.to_i

# Return a random word from the dictionary, lowercased
def random_word
  %x[sed -n '#{rand(DICT_LINES)} {p;q;}' '#{DICT_PATH}'].chomp.downcase
end

# Return a random word that consists of only lowercase letters
def random_ascii_word
  word = random_word
  while word =~ /[^a-z]/
    word = random_word
  end 
  return word
end

# Generate a passphrase of at least the given length in characters
def generate(length)
  phrase = ''
  while phrase.length < length
    phrase += random_ascii_word + ' '
  end
  return phrase.chomp
end

if ARGV.count == 0
  puts USAGE
else
  length = ARGV[0].to_i
  puts generate(length)
end