pwgen.py 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. #!/usr/bin/python
  2. """generate word compound passwords
  3. usage: pwgen -c [number_of_phrases default=1]
  4. or pwgen [len default=20] [number_of_phrases default=1] // no conjunctions
  5. -c use conjunction
  6. """
  7. import random, sys
  8. targetLen = 20 # default pw len
  9. useConjunction = False
  10. number = 1
  11. def toInt(s, chkRange, errStr = "sorry, that's not a number", rangeStr = "sorry, I can't do that number"):
  12. try:
  13. t = int(s)
  14. except:
  15. print errStr
  16. sys.exit()
  17. if t<chkRange[0] or t>chkRange[1]:
  18. print rangeStr
  19. sys.exit()
  20. return t
  21. if len(sys.argv)>1:
  22. if sys.argv[1]=="-h" or sys.argv[1]=="--help":
  23. print "pwgen.py v1.0 generate passphrase; inspired by xkcd/936 and SteveGibson\n"
  24. print "Usage: pwgen.py [length [num_phrases]] "
  25. print " pwgen.py -c [num_phrases]"
  26. print " pwgen.py -h | --help \n"
  27. print " length make pass phrases padded with punctuation filler; default=20"
  28. print " -c make 2 word pass phrases with a conjuction filler"
  29. print " num_phrases make multiple pass phrases, one per line; default=1\n"
  30. sys.exit()
  31. if sys.argv[1]=="-c": # conjunction mode
  32. useConjunction = True
  33. else: # the next number is the length
  34. targetLen = toInt(sys.argv[1],[12,36],rangeStr = "Sorry, I can't build phrases that long")
  35. if len(sys.argv)>2:
  36. number = toInt(sys.argv[2],[0,40]) # pick off the number of phrases
  37. f = open("/usr/share/dict/words")
  38. d = f.readlines()
  39. f.close()
  40. numWords = len(d)
  41. for i in range(number):
  42. w=['','','']
  43. for i in range(3):
  44. w[i] = d[random.randint(0,numWords-1)][:-1] # toss out trailing \n
  45. while len(w[i]) > 10:
  46. w[i] = d[random.randint(0,numWords-1)][:-1] # toss out long words
  47. whole = len(w[0])+len(w[1])
  48. punc = " !@#$%^&*()-_=+[{]}\|;:/?.>,<`~"
  49. thisPunct = punc[int(random.random() * len(punc))]
  50. conjunctions = ["and", "and a", "and the","or", "or the", "or a",
  51. "with a", "with", "with the", "by a", "by the",
  52. "on a", "on the","on", "in a", "in the", "in",
  53. "for", "for a", "for the"]
  54. if useConjunction == False:
  55. if whole >= targetLen - 6: # if 2 words is enough
  56. r = targetLen - whole
  57. pw = w[0] + thisPunct*r + w[1]
  58. else: # otherwise use 3
  59. whole = whole + len(w[2])
  60. r = targetLen - whole
  61. pw = w[0] + thisPunct*int(r/2) + w[1] + thisPunct*int(r/2) + w[2]
  62. else:
  63. conj = conjunctions[random.randint(0,len(conjunctions)-1)]
  64. if w[1][0].lower() in ['a','A','e','E','i','I','o','O','u','U']:
  65. if conj[-2:]==" a":
  66. conj = conj+'n'
  67. pw = w[0] + ' ' + conj + ' ' + w[1]
  68. print pw