My password generator

January 30th, 2010

How do you create a really good password that you don't need to remember but that you might occasionally need to write on paper or type into a keyboard? These days modern operating system provide really good sources of randomness, and one method that is often used is to read some randomness from the operating system PRNG located at /dev/random and run the data through the base64 encoding to get letters, numbers, + (plus) and / (slash). However, those passwords are not that conveinent and sometimes when I write them down people mistake my zeroes for capital o and things like that.

What I wanted was a password generator that could output a configurable length password using only easily distinguishable letters and numbers, so I wrote one. As usual I place this code in the public domain, feel free to use it any way you want.

Features:

  1. The entropy of the password is as good as the underlying operating system. If you use a recent Linux or OSX version, the data returned from /dev/random is quite good.
  2. The code is simple and it is easy to verify that the program actually uses the entropy that it reads.
  3. The resulting passwords are easy to type on keyboards and write on paper without confusing the reader with similar characters such as 1 (one) and l (lower case l).
  4. The length of the password is configurable.
#!/usr/bin/python
 
import sys
 
# alphanumeric chars minus l, I, O, 0, 1
alphabet = "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789"
# Some expeimentation told me that 2 ** 5.8 = 55.7
BITS_PER_CHAR = 5.8
 
# The default password length has the capacity of a bit more
# than 64 bits of entropy.
DEFAULT_LEN = 12
 
def main(args):
	count = DEFAULT_LEN
	if len(args) > 1:
		if args[1] == '-h':
			usage()
			return
		elif args[1] == '-c' and len(args) > 2:
			count = int(sys.argv[2])
		else:
			usage()
			return
	print(create_password(count))
 
def string_to_bignum(s):
	num = 0
	for c in s:
		num = ord(c) + (num << 8);
	return num
 
def create_password(length):
	random = open("/dev/random", "r")
	needed_bytes = (int)(length * BITS_PER_CHAR) / 8 + 1
	n = string_to_bignum(random.read(needed_bytes))
	random.close()
	s = ""
	for i in xrange(length):
		s = s + alphabet[n % len(alphabet)]
		n = n / len(alphabet)
	return s
 
def usage():
	print """mkpasswd [-h] [-c COUNT]
Create a random password using the operating system's entropy pool
using a 57 character alphabet of letters and numbers. The characters
in the alphabet excludes characters and letters easily confusable such
as I and 1. 
 
Each password character holds about 5.8 bits of entropy, so the
standard 12 character password can hold a theroretical maximum of
69 bits of entropy.
 
The actual entropy present in any generated password is a function
of the entropy gathering algortihm present in the kernel of your
operating system.
 
  -h        display this help text
  -c COUNT  create a password with COUNT characters."""  
 
if __name__ == '__main__':
	main(sys.argv)

One Response to “My password generator”

  1. Jonathan Allen on May 20, 2010 19:39

    For me, the best operating system is Linux because it rarely hangs.;`’

Trackback URI | Comments RSS

Leave a Reply

Name (required)

Email (required)

Website

Speak your mind