pwgen.py 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  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. punc = " !@#$%^&*()-_=+[{]}\|;:/?.>,<`~"
  12. number_punc = "0123456789"
  13. def toInt(s, chkRange, errStr = "sorry, that's not a number", rangeStr = "sorry, I can't do that number"):
  14. try:
  15. t = int(s)
  16. except:
  17. print errStr
  18. sys.exit()
  19. if t<chkRange[0] or t>chkRange[1]:
  20. print rangeStr
  21. sys.exit()
  22. return t
  23. narg = 1
  24. if len(sys.argv)>1:
  25. if sys.argv[1]=="-h" or sys.argv[1]=="--help":
  26. print "pwgen.py v1.3 generate passphrase; inspired by xkcd/936 and SteveGibson\n"
  27. print "Usage: pwgen.py [-p | -P | -n | -N] [length [num_phrases]] "
  28. print " pwgen.py -c [num_phrases]"
  29. print " pwgen.py -h | --help \n"
  30. print " -p pad with only spaces (for smartphone)"
  31. print " -P pad with spaces, period and comma (for smartphone)"
  32. print " -n pad with numbers"
  33. print " -N pad with numbers, spaces, period, comma like -P -n"
  34. print " length make pass phrases padded with punctuation filler; default=20"
  35. print " -c make 2 word pass phrases with a conjuction filler"
  36. print " num_phrases make multiple pass phrases, one per line; default=1\n"
  37. sys.exit()
  38. elif sys.argv[1]=="-c": # conjunction mode
  39. useConjunction = True
  40. narg = narg + 1
  41. elif sys.argv[1]=='-n': # number fill mode
  42. punc = number_punc
  43. narg = narg + 1
  44. elif sys.argv[1]=='-N':
  45. punc = number_punc + " ,."
  46. narg = narg + 1
  47. elif sys.argv[1]=="-p": # use only space
  48. punc = " "
  49. narg = narg + 1
  50. elif sys.argv[1]=="-P":
  51. punc = " .,"
  52. narg = narg + 1
  53. if not useConjunction:
  54. if len(sys.argv)>narg:
  55. targetLen = toInt(sys.argv[narg],[12,36],rangeStr = "Sorry, I can't build phrases that long")
  56. narg = narg + 1
  57. if len(sys.argv)>narg:
  58. number = toInt(sys.argv[narg],[0,40]) # pick off the number of phrases
  59. f = open("/usr/share/dict/words")
  60. #f = open("/usr/share/dict/corncob_lowercase.txt")
  61. d = f.read().splitlines()
  62. f.close()
  63. numWords = len(d)
  64. for i in range(number):
  65. w=['','','']
  66. for i in range(3):
  67. w[i] = d[random.randint(0,numWords-1)]
  68. while (len(w[i]) > 10) or (w[i].endswith("'s")):
  69. w[i] = d[random.randint(0,numWords-1)]
  70. whole = len(w[0])+len(w[1])
  71. thisPunct = punc[int(random.random() * len(punc))]
  72. conjunctions = ["and", "and a", "and the","or", "or the", "or a",
  73. "with a", "with", "with the", "by a", "by the",
  74. "on a", "on the","on", "in a", "in the", "in",
  75. "for", "for a", "for the"]
  76. if useConjunction == False:
  77. if whole + 6 >= targetLen: # if 2 words is enough
  78. r = max(1,targetLen - whole)
  79. pw = w[0] + thisPunct*r + w[1]
  80. else: # otherwise use 3
  81. whole = whole + len(w[2])
  82. r = targetLen - whole
  83. if r<2:
  84. r = 2
  85. pw = w[0] + thisPunct*(r/2) + w[1] + thisPunct*(r-r/2) + w[2]
  86. else:
  87. conj = conjunctions[random.randint(0,len(conjunctions)-1)]
  88. if w[1][0].lower() in ['a','A','e','E','i','I','o','O','u','U']:
  89. if conj[-2:]==" a":
  90. conj = conj+'n'
  91. pw = w[0] + ' ' + conj + ' ' + w[1]
  92. print pw
  93. """
  94. although this
  95. read n; i="1"; while [ $i -le $n ]; do cat /etc/dictionaries-common/words | shuf | head -1; i=$(( $i + 1 )); done
  96. will do the job almost as well
  97. """