run.py 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. # This program is Free Software. You can use it either under the terms of
  2. # the GNU GPL version 3 or any later version. (c) J.Y.Amihud 2021
  3. # This program is a very basic terminal based password manager.
  4. from modules import hcu
  5. # Rending an ASCI art thingy
  6. print("""
  7. ##########################################################
  8. # #
  9. # .-..-. .-. #
  10. # | || | | | #
  11. # | | \ \| | #
  12. # .- | | _\ / _ #
  13. # ____ | \_/ // \| |/ \ #
  14. # | _ \ \___/ \_/'-'\_/ #
  15. # | |_)|____ ____ #
  16. # | __/ \.----.----.-----./ \.----.----. #
  17. # | | | /\ | --| --| | | | /\ | -- | \ | #
  18. # | | | __ |-- |-- | . | \/ | \ | / | #
  19. # '-' '-' '-'----'----'-----'\____/'----'----' #
  20. # #
  21. # #
  22. # #
  23. # (C) J.Y.Amihud 2021 GNU GPL v3 or later #
  24. # #
  25. ##########################################################
  26. """)
  27. # login is just going to be an .hcu file. Which is a jason database
  28. # This will make it easy to pull out data
  29. import os
  30. import json
  31. from getpass import getpass
  32. from modules import hcu
  33. def login():
  34. login = input("Login: ")
  35. password = getpass("Password: ")
  36. # logic has to have .hcu in the end of it
  37. if not login.endswith(".hcu"):
  38. login = login+".hcu"
  39. # if the file is doesn't exist, make new file
  40. try:
  41. f = open(login, "r")
  42. except:
  43. print("File ["+login+"] doesn't exist. \nCreate? (y/n)")
  44. ans = input(":")
  45. if ans.lower() in ["y", "yes", "true"]:
  46. f = open(login, "w") # Making file
  47. f.write(hcu.hash(password)) # Giving a password hash.
  48. # New data
  49. newdata = json.dumps({})
  50. # Sometimes you want to restore data from a file
  51. try:
  52. restore = open("errordump_"+login.replace("/","_")+".data", "r")
  53. print("Restore? (y/n)")
  54. ans = input(":")
  55. if ans.lower() in ["y", "yes", "true"]:
  56. newdata = restore.read()
  57. except:
  58. pass
  59. f.write(hcu.code(newdata, password))
  60. f.close() # Exiting file
  61. f = open(login, "r") # reading it again
  62. else:
  63. return False
  64. # Checking that the password is correct
  65. if f.read(20) != hcu.hash(password):
  66. print("Wrong Password!")
  67. return False
  68. else:
  69. return([hcu.uncode(f.read(), password), password, login])
  70. # Loging in
  71. f = False
  72. for i in range(10):
  73. if not f:
  74. f = login()
  75. # If tried to login more then 10 times
  76. if not f:
  77. print("Login failed.")
  78. input()
  79. exit()
  80. # If you launched. We gonna need a few functions.
  81. # we need to make sure that people do not loose their
  82. # passwords
  83. try:
  84. data = json.loads(f[0])
  85. except Exception as e:
  86. print("WARNING! File is corrupted")
  87. print("Json decoding has failed: \n["+str(e)+"]")
  88. # Writing a special file to restore file later
  89. x = open("errordump_"+f[2].replace("/","_")+".data", "w")
  90. x.write(f[0])
  91. x.close()
  92. print("The un-encrypted data was saved to: errordump_"+f[2].replace("/","_")+".data")
  93. # Pause
  94. input()
  95. print(""" Restoring of data could be done! Don't worry.
  96. 1.) Open the errordump_"""+f[2].replace("/","_")+""".data file
  97. in the directory of the software.
  98. 2.) Edit out all weird and strange characters. To preserve the JSON
  99. format, as it supposed to be. Save changes.
  100. 3.) Delete the """+f[2]+""" file.
  101. 4.) Try to login as usual. It will ask you to create new login. Do it.
  102. It will ask you to restore, do it.
  103. 5.) Delete the errordump_"""+f[2].replace("/","_")+""".data file when
  104. restoration is successful. Test multiple times that you can enter
  105. your file, before deleting the un-encrypted backup.
  106. """)
  107. input()
  108. print("Please report this bug to:")
  109. print("https://notabug.org/jyamihud/JYPassword/issues")
  110. exit()
  111. password = f[1]
  112. login = f[2]
  113. print(len(data), """sites loaded.
  114. Type list to list all sites.
  115. Type help to get functions.
  116. """)
  117. # Main loop
  118. select = ""
  119. while True:
  120. c = input(":")
  121. # little program to make it simpler to use. You could
  122. # input a number of a thing instead of the whole name
  123. try:
  124. c = int(c)
  125. # If you typed a number instead of the full name
  126. # it's going to be a shortcut, sometimes names
  127. # are too complex. And this is not cool.
  128. if not select:
  129. # If no site is selected
  130. # Then we are selecting from the list of sites
  131. c = list(data.keys())[c]
  132. else:
  133. c = list(data[select].keys())[c]
  134. # Not all commands are numbers. And not all numbers are
  135. # in a given dictionary. So I use a simple try: except:
  136. # here. Yell at me if you want.
  137. except:
  138. pass
  139. if c == "exit":
  140. exit()
  141. elif c == "help":
  142. print ("""
  143. exit - Exits the software
  144. help - Prints this help
  145. list - List all sites
  146. news - Adds a new site
  147. newl - Add or edit a login
  148. cpas - Change main password
  149. """)
  150. # list all sites available in the file
  151. elif c == "list":
  152. for n, i in enumerate(data):
  153. print("[",n,"]",i)
  154. select = ""
  155. # add a new site to the list
  156. elif c == "news":
  157. site = input("New site name: ")
  158. if site not in data:
  159. data[site] = {}
  160. select = site
  161. print(len(data[select]), "logins in "+c)
  162. # User might want to change the password of the file
  163. elif c == "cpas":
  164. # we gonna check that the user knows previous password
  165. check = getpass("Old Password: ")
  166. if check == password:
  167. password = getpass("New Password: ")
  168. else:
  169. print("Wrong Password!")
  170. # if you type the name of the site then select the site
  171. elif c in data:
  172. print(len(data[c]), "logins in "+c)
  173. for n, i in enumerate(data[c]):
  174. print("[",n,"]",i, " : "+"*"*len(data[c][i]))
  175. select = c
  176. # if any site is selected we gonna do a few more things
  177. elif select:
  178. # if you typed in a login from the site show password
  179. if c in data[select]:
  180. # but first we gonna check your password for this file
  181. check = getpass("Password: ")
  182. if check == password:
  183. print(" "+data[select][c], end="\r")
  184. # Showing the password only for some time
  185. import time
  186. time.sleep(4)
  187. # Turning the password into ******** after few seconds
  188. ncols = len(data[select][c])
  189. print(" "+"*"*ncols)
  190. else:
  191. print("Wrong Password!")
  192. # if you want to add or edit a login
  193. if c == "newl":
  194. nlog = str(input(select+" login: "))
  195. # auto generate password?
  196. print("Auto-generate password? (y/n)")
  197. ans = input(": ")
  198. # Small random generator
  199. if ans.lower() in ["y", "yes", "true"]:
  200. import random
  201. npass = ""
  202. for i in range(20):
  203. npass = npass + random.choice(
  204. "`1234567890-=~!@#$%^&*()__+qwertyuiop[]asdfghjkl;'zxcvbnm,./QWERTYUIOP{}ASDFGHJKL:|ZXCVBNM<>?")
  205. # If you don't want to auto-generate, you can always type by hand
  206. else:
  207. npass = str(getpass(select+" password: "))
  208. # There is some json issues with these simbols. So let's
  209. # avoid them.
  210. npass = npass.replace('"', "'").replace("\\", "/")
  211. # adding the password to the list
  212. data[select][nlog] = npass
  213. # It will save automatically after each thing done
  214. f = open(login, "w") # Making file
  215. f.write(hcu.hash(password)) # Giving a password hash.
  216. f.write(hcu.code(json.dumps(data), password))
  217. f.close() # Exiting file