|
@@ -2,62 +2,82 @@
|
|
|
|
|
|
"""generate word compound passwords
|
|
"""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
|
|
-c use conjunction
|
|
"""
|
|
"""
|
|
import random, sys
|
|
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:
|
|
try:
|
|
- target_arg = int(target_arg)
|
|
|
|
|
|
+ t = int(s)
|
|
except:
|
|
except:
|
|
- print "sorry, you need to give me a number"
|
|
|
|
|
|
+ print errStr
|
|
sys.exit()
|
|
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()
|
|
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")
|
|
f = open("/usr/share/dict/words")
|
|
d = f.readlines()
|
|
d = f.readlines()
|
|
f.close()
|
|
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
|
|
|
|
|