|  | @@ -2,62 +2,82 @@
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  """generate word compound passwords 
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -usage: pwgen [-c] [len default=20]
 | 
	
		
			
				|  |  | +usage: pwgen -c [number_of_phrases default=1]
 | 
	
		
			
				|  |  | +or     pwgen [len default=20] [number_of_phrases default=1]    // no conjunctions
 | 
	
		
			
				|  |  |  	-c   use conjunction
 | 
	
		
			
				|  |  |  """
 | 
	
		
			
				|  |  |  import random, sys
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -target = 20		# default pw len
 | 
	
		
			
				|  |  | -use_conjunction = False
 | 
	
		
			
				|  |  | +targetLen = 20		# default pw len
 | 
	
		
			
				|  |  | +useConjunction = False
 | 
	
		
			
				|  |  | +number = 1
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -n = 1
 | 
	
		
			
				|  |  | -if len(sys.argv)>1 and sys.argv[1]=="-c":
 | 
	
		
			
				|  |  | -	use_conjunction = True
 | 
	
		
			
				|  |  | -	n = 2
 | 
	
		
			
				|  |  | -if len(sys.argv)>n:
 | 
	
		
			
				|  |  | -	target_arg = sys.argv[n]	# if a len is spec'd on the cmd line
 | 
	
		
			
				|  |  | +def toInt(s, chkRange, errStr = "sorry, that's not a number", rangeStr = "sorry, I can't do that number"):
 | 
	
		
			
				|  |  |  	try:
 | 
	
		
			
				|  |  | -		target_arg = int(target_arg)
 | 
	
		
			
				|  |  | +		t = int(s)
 | 
	
		
			
				|  |  |  	except:
 | 
	
		
			
				|  |  | -		print "sorry, you need to give me a number"
 | 
	
		
			
				|  |  | +		print errStr
 | 
	
		
			
				|  |  |  		sys.exit()
 | 
	
		
			
				|  |  | -	if target_arg<12 or target_arg>40:
 | 
	
		
			
				|  |  | -		print "sorry, can't do that length"
 | 
	
		
			
				|  |  | +	if t<chkRange[0] or t>chkRange[1]:
 | 
	
		
			
				|  |  | +		print rangeStr
 | 
	
		
			
				|  |  |  		sys.exit()
 | 
	
		
			
				|  |  | -	target = target_arg
 | 
	
		
			
				|  |  | +	return t
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +if len(sys.argv)>1:
 | 
	
		
			
				|  |  | +	if sys.argv[1]=="-h" or sys.argv[1]=="--help":
 | 
	
		
			
				|  |  | +		print "pwgen.py  v1.0  generate passphrase; inspired by xkcd/936 and SteveGibson\n"
 | 
	
		
			
				|  |  | +		print "Usage: pwgen.py [length [num_phrases]] "
 | 
	
		
			
				|  |  | +		print "       pwgen.py -c [num_phrases]"
 | 
	
		
			
				|  |  | +		print "       pwgen.py -h | --help \n"
 | 
	
		
			
				|  |  | +		print "     length       make pass phrases padded with punctuation filler; default=20"
 | 
	
		
			
				|  |  | +		print "     -c           make 2 word pass phrases with a conjuction filler"
 | 
	
		
			
				|  |  | +		print "     num_phrases  make multiple pass phrases, one per line; default=1\n"
 | 
	
		
			
				|  |  | +		sys.exit()
 | 
	
		
			
				|  |  | +	if sys.argv[1]=="-c":	# conjunction mode
 | 
	
		
			
				|  |  | +		useConjunction = True
 | 
	
		
			
				|  |  | +	else:				# the next number is the length
 | 
	
		
			
				|  |  | +		targetLen = toInt(sys.argv[1],[12,36],rangeStr = "Sorry, I can't build phrases that long")
 | 
	
		
			
				|  |  | +	if len(sys.argv)>2:
 | 
	
		
			
				|  |  | +		number = toInt(sys.argv[2],[0,40])  # pick off the number of phrases
 | 
	
		
			
				|  |  | + 
 | 
	
		
			
				|  |  |  f = open("/usr/share/dict/words")
 | 
	
		
			
				|  |  |  d = f.readlines()
 | 
	
		
			
				|  |  |  f.close()
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -num = len(d)	
 | 
	
		
			
				|  |  | +numWords = len(d)	
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +for i in range(number):
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	w=['','','']
 | 
	
		
			
				|  |  | +	for i in range(3):
 | 
	
		
			
				|  |  | +		w[i] = d[random.randint(0,numWords-1)][:-1]  # toss out trailing \n
 | 
	
		
			
				|  |  | +		while len(w[i]) > 10:
 | 
	
		
			
				|  |  | +			w[i] = d[random.randint(0,numWords-1)][:-1]	# toss out long words
 | 
	
		
			
				|  |  | +			
 | 
	
		
			
				|  |  | +	whole = len(w[0])+len(w[1])
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	punc = " !@#$%^&*()-_=+[{]}\|;:/?.>,<`~"
 | 
	
		
			
				|  |  | +	thisPunct = punc[int(random.random() * len(punc))] 
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	conjunctions = ["and", "and a", "and the","or", "or the", "or a", 
 | 
	
		
			
				|  |  | +		"with a", "with", "with the", "by a", "by the", 
 | 
	
		
			
				|  |  | +		"on a", "on the","on", "in a", "in the", "in", 
 | 
	
		
			
				|  |  | +		"for", "for a", "for the"]
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -w=['','','']
 | 
	
		
			
				|  |  | -for i in range(3):
 | 
	
		
			
				|  |  | -	w[i] = d[random.randint(0,num-1)][:-1]  # toss out trailing \n
 | 
	
		
			
				|  |  | -	while len(w[i]) > 10:
 | 
	
		
			
				|  |  | -		w[i] = d[random.randint(0,num-1)][:-1]	# toss out long words
 | 
	
		
			
				|  |  | +	if useConjunction == False:
 | 
	
		
			
				|  |  | +		if whole >= targetLen - 6:	# if 2 words is enough
 | 
	
		
			
				|  |  | +			r = targetLen - whole
 | 
	
		
			
				|  |  | +			pw = w[0] + thisPunct*r + w[1]
 | 
	
		
			
				|  |  | +		else:		# otherwise use 3
 | 
	
		
			
				|  |  | +			whole = whole + len(w[2])
 | 
	
		
			
				|  |  | +			r = targetLen - whole
 | 
	
		
			
				|  |  | +			pw = w[0] + thisPunct*int(r/2) + w[1] + thisPunct*int(r/2) + w[2]
 | 
	
		
			
				|  |  | +	else:
 | 
	
		
			
				|  |  | +		conj = conjunctions[random.randint(0,len(conjunctions)-1)]
 | 
	
		
			
				|  |  | +		if w[1][0].lower() in ['a','A','e','E','i','I','o','O','u','U']:
 | 
	
		
			
				|  |  | +			if conj[-2:]==" a":
 | 
	
		
			
				|  |  | +				conj = conj+'n'
 | 
	
		
			
				|  |  | +		pw = w[0] + ' ' + conj + ' ' + w[1]
 | 
	
		
			
				|  |  |  		
 | 
	
		
			
				|  |  | -whole = len(w[0])+len(w[1])
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -punc = " !@#$%^&*()-_=+[{]}\|;:/?.>,<`~"
 | 
	
		
			
				|  |  | -this_punc = punc[int(random.random() * len(punc))] 
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -conjunctions = [" and ", " and a ", " and the "," or ", " or the ", " or a ", 
 | 
	
		
			
				|  |  | -	" with a ", " with ", " with the ", " by a ", " by the ", 
 | 
	
		
			
				|  |  | -	" on a ", " on the "," on ", " in a ", " in the ", " in ", 
 | 
	
		
			
				|  |  | -	" for ", " for a ", " for the "]
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -if use_conjunction == False:
 | 
	
		
			
				|  |  | -	if whole >= target-6:	# if 2 words is enough
 | 
	
		
			
				|  |  | -		r = target-whole
 | 
	
		
			
				|  |  | -		pw = w[0] + this_punc*r + w[1]
 | 
	
		
			
				|  |  | -	else:		# otherwise use 3
 | 
	
		
			
				|  |  | -		whole = whole + len(w[2])
 | 
	
		
			
				|  |  | -		r = target-whole
 | 
	
		
			
				|  |  | -		pw = w[0] + this_punc*int(r/2) + w[1] + this_punc*int(r/2) + w[2]
 | 
	
		
			
				|  |  | -else:
 | 
	
		
			
				|  |  | -	pw = w[0] + conjunctions[random.randint(0,len(conjunctions)-1)] + w[1]
 | 
	
		
			
				|  |  | -	
 | 
	
		
			
				|  |  | -print "pass phrase: "+pw
 | 
	
		
			
				|  |  | +	print pw
 | 
	
		
			
				|  |  |  
 |