pypassgen 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. #!/usr/bin/env python
  2. #
  3. # This is a port of classical passgen (provided by jxself) into the python
  4. # language.
  5. #
  6. # Hey, given a portable python installation in Windows, we could even have
  7. # a graphical version of this program with GTK3
  8. #
  9. # Copyright (C) 2016 - kzimmermann <https://quitter.se/kzimmermann>
  10. #
  11. # This program is free software: you can redistribute it and/or modify
  12. # it under the terms of the GNU General Public License as published by
  13. # the Free Software Foundation, either version 3 of the License, or
  14. # (at your option) any later version.
  15. #
  16. # This program is distributed in the hope that it will be useful,
  17. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. # GNU General Public License for more details.
  20. #
  21. # You should have received a copy of the GNU General Public License
  22. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  23. #
  24. import sys
  25. import base64 as b64
  26. import hashlib
  27. from getpass import getpass
  28. #---- Standard configuration variables:
  29. seclevel = 7 # how many times tokens are hashed
  30. #---- Functions:
  31. def secure_hash(token):
  32. """
  33. Hashes multiple times a given string so as to provide something that should
  34. not be easy to reverse. Standardized as seven times, but feel free to
  35. change it to as much as your own paranoia needs.
  36. Returns a SHA-256 hash.
  37. """
  38. temp = str(token)
  39. for i in xrange(seclevel):
  40. temp = hashlib.sha256(temp).hexdigest()
  41. return temp
  42. def generate(salt, string):
  43. """
  44. Generates a 32-char long password based on algorithm v1 (hash then encode).
  45. Arguments are a password seed (called a salt) and a service-specific string
  46. so all passwords generated will be different.
  47. The 32 characters are sampled from a different position depending on the
  48. salt used. This should always work provided that the salt isn't too long.
  49. """
  50. # So that the sampling is not that obvious ;)
  51. start = len("%s%s" % (salt, string))
  52. temp = secure_hash("%s%s" % (salt, string))
  53. return b64.b64encode(temp)[start:start+32]
  54. def main():
  55. """
  56. Main interaction when module has not been imported
  57. """
  58. while True:
  59. seed = getpass("Enter your salt: ")
  60. seed_confirm = getpass("Confirm: ")
  61. if seed == seed_confirm:
  62. break
  63. else:
  64. print "Salts don't match. Try again."
  65. if len(sys.argv) == 1:
  66. string = raw_input("Enter your string: ")
  67. elif len(sys.argv) == 2:
  68. string = sys.argv[1]
  69. print generate(seed, string)
  70. if __name__ == "__main__":
  71. main()
  72. sys.exit(0)