def addField(self, key, value): ''' data = GET /@username POST /@username data add { key : value } Adds the @key @value pair to the current user details stored in the db. Gets the currently stored details, decrypts it using the user's secret key, adds the new key-value pair, encrypts it, then sends it back to the db. Details (eg pair 'first name' 'john') are used to fill forms. Cookie used to check authorization by server. ''' if (self.isAuthenticated()): header = {"Cookie": self.cookie} r = self.session.get(self.host + "/" + self.user, headers=header) if (r.status_code == 200): data = {} if r.text: dec_data = CryptUtils.decrypt(r.text, self.key) data = json.loads(dec_data) data[key] = value json_data = json.dumps(data) enc_data = CryptUtils.encrypt(json_data, self.key) headers = { "content-length": str(len(enc_data)), "Cookie": self.cookie } r = self.session.post(self.host + "/" + self.user, data=enc_data, headers=headers) print(r.text) else: print("Adding field failed, please try again") else: print("No user logged in")
def register(self, post_data): ''' Adds a new user to the system. Checks if the username is available, and stores the hashes and salts the password sent before storing. Also stores the salt for the key and password. ''' try: username = post_data["username"] if username in users.keys(): self._set_headers(503) self.wfile.write("The username is not available".encode()) return hash_pwd = post_data["hash_pwd"] key_salt = post_data["key_salt"] pwd_salt = CryptUtils.genSalt() pwd_to_store = CryptUtils.saltAndHash(pwd_salt, hash_pwd) users[username] = { "password": pwd_to_store, "pwd_salt": pwd_salt, "key_salt": key_salt } database[username] = "" self._set_headers(200) self.wfile.write( ("User " + username + " has been created. Please login to continue.").encode()) except (Exception): print(e) self._set_headers(503) self.wfile.write( "Registration of user failed, please try again.".encode())
def login(self, post_data): ''' Attempts to login to the system using the username and password sent in @post_data. Salts and hashes the password sent to verify credentials. Send an auth cookie back with a token and timestamp for future verification of credentials. Also, sends the key_salt to the client. ''' try: username = post_data["username"] password = post_data["password"] user = users[username] pwd = user["password"] salt = user["pwd_salt"] password = CryptUtils.saltAndHash(salt, password) if (password == pwd): key_salt = user["key_salt"] ts = str(dt.datetime.now()) auth_token = self.genAuthToken(username, password, ts) cookie = json.dumps({"AUTH": auth_token, "TIMESTAMP": ts}) self._set_headers(200, cookie=cookie) self.wfile.write(("salt=" + key_salt).encode()) print(key_salt) print(username + " has logged in") return else: self._set_headers(401) self.wfile.write("Invalid user".encode()) print(username + " failed to log in") return except (KeyError) as e: print(e) print("Invalid username login") self._set_headers(401) self.wfile.write("Invalid user".encode())
def genAuthToken(self, username, password, ts): ''' Generates the tag (i.e. hmac(@username : @password : @ts)) using the server's secret key (@KEY) ''' mac_msg = username + ":" + password + ":" + ts return CryptUtils.mac(mac_msg, KEY)
def addUser(self, username, pwd): ''' POST /adduser {username: @username, hash_pwd: sha256(@pwd), key_salt: salt} Generates salt (for generation of secret key), requests for a new user to be added to the system. @pwd is hashed (sha256) before it is sent to the server. ''' hash_pwd = CryptUtils.sha256(pwd) key_salt = CryptUtils.genSalt() #print("key salt: " + key_salt) #print("hpwd:" + hash_pwd) data = { "username": username, "hash_pwd": hash_pwd, "key_salt": key_salt } json_data = json.dumps(data) headers = {"content-length": str(len(json_data))} r = self.session.post(self.host + "/adduser", data=json_data, headers=headers) print(r.text)
def login(self, username, password): ''' POST /login {username: @username, password: @password} Attempts to log into the system with @username and @password. Hashes the password with sha256 before sending to the server to ensure that the server never knows the plaintext password of the user (which is used to generate the secret key of the user). ''' auth = {'username': username, 'password': CryptUtils.sha256(password)} json_data = json.dumps(auth) headers = {"content-length": str(len(json_data))} r = self.session.post(self.host + "/login", data=json_data, headers=headers) if (r.status_code == 200): print("Welcome " + username) data = r.text salt = data.split('=')[1].encode() self.user = username self.key = CryptUtils.genKey(password, salt) self.cookie = r.headers['Set-Cookie'] else: print("Invalid username or password")
def getFields(self): ''' GET /@username Gets all details of the current logged-in user and decrypts the fields. Cookie used to check authorization by server. ''' if (self.isAuthenticated()): header = {"Cookie": self.cookie} r = self.session.get(self.host + "/" + self.user, headers=header) if r.text: dec_data = CryptUtils.decrypt(r.text, self.key) print(dec_data) else: print(self.user + " has no data") else: print("No user logged in")
def fill(self, pdf, out_file): ''' Fills out @pdf form fields with the data of the current user. Output into @outfile ''' print("Filling form: " + pdf) if (self.isAuthenticated()): r = self.session.get(self.host + "/" + self.user) if (r.text == ""): print("User has no data to fill") return plaintext = CryptUtils.decrypt(r.text, self.key) data = json.loads(plaintext) try: Filler.fill(data, pdf, out_file) print("Successfully filled in " + out_file) except (Exception) as e: print(e) print("Please input a valid pdf") else: print("No user logged in")