def getPrivateData(self): url_get = "http://cs302.kiwi.land/api/get_privatedata" headers = self.createAuthorisedHeader(True) try: JSON_object = helper.postJson(None, headers, url_get) response = JSON_object.get("response", None) except Exception as e: print(e) return {} else: private_data = {} if response == "ok": private_data_encr = JSON_object.get("privatedata", None) if not private_data_encr: return {} private_data_bytes = base64.b64decode(private_data_encr) try: key = helper.getSymmetricKeyFromPassword(self.password2) private_data_str = helper.decryptStringKey( key, private_data_bytes) except nacl.exceptions.CryptoError as e: print(e) return 1 except Exception as e: print(e) return 1 else: private_data = json.loads(private_data_str) return private_data
def pingCheckUsers(self): headers = self.createAuthorisedHeader(False) ts = str(time.time()) all_users = database.getAllUsers() payload = { "my_time": ts, "connection_address": self.logserv.connection_address, "connection_location": self.logserv.connection_location } for user in all_users: username = user.get("username", None) user_address = user.get("address", None) user_status = user.get("status", None) if user_address is None or user_status != "online": continue url = "http://" + user_address + "/api/ping_check" try: JSON_object = helper.postJson(payload, headers, url) response = JSON_object.get("response", None) if response == "ok": print("ping check successful") else: print("ping check not ok") database.makeUserOffline(username) except: print("cannot ping this user!!!!") database.makeUserOffline(username)
def reportUser(self, status=None): print("reporting user" + str(self.username)) headers = self.createAuthorisedHeader(True) url = "http://cs302.kiwi.land/api/report" pubkey = self.signing_key.verify_key pubkey_hex = pubkey.encode(encoder=nacl.encoding.HexEncoder) pubkey_hex_str = pubkey_hex.decode('utf-8') connection_address = self.connection_address connection_location = self.connection_location if not status: status = self.status payload = { "connection_address": connection_address, "connection_location": connection_location, "incoming_pubkey": pubkey_hex_str, "status": status } try: JSON_object = helper.postJson(payload, headers, url) response = JSON_object.get("response", None) if response == "ok": return 0 else: raise Exception("response not ok") except Exception as e: print(e) return 1
def testPublicKey(self): url = "http://cs302.kiwi.land/api/ping" if self.signing_key is None: return 1 pubkey = self.signing_key.verify_key pubkey_hex = pubkey.encode(encoder=nacl.encoding.HexEncoder) pubkey_hex_str = pubkey_hex.decode('utf-8') #creating message and then signed message_bytes = bytes(pubkey_hex_str, encoding='utf-8') signed = self.signing_key.sign(message_bytes, encoder=nacl.encoding.HexEncoder) signature_hex_str = signed.signature.decode('utf-8') headers = self.createAuthorisedHeader(True) payload = {"pubkey": pubkey_hex_str, "signature": signature_hex_str} JSON_object = helper.postJson(payload, headers, url) response = JSON_object.get("response", None) signature = JSON_object.get("signature", None) if response == "ok" and signature == "ok": print("public key and signature is valid.") return 0 else: print(JSON_object) print(response) print(signature) print(pubkey_hex_str) print("public key and or signature is invalid.") return 1
def checkPublicKey(self, pubkey_str): headers = self.createAuthorisedHeader(True) url = "http://cs302.kiwi.land/api/list_users" req = "?pubkey=" + pubkey_str JSON_object = helper.postJson(None, headers, url + req) response = JSON_object.get("response", None) if response == 'ok': self.users = JSON_object.get("users", None) return 0 else: return 1
def getLoginServerRecord(self): url = "http://cs302.kiwi.land/api/get_loginserver_record" headers = self.createAuthorisedHeader(True) JSON_object = helper.postJson(None, headers, url) response = JSON_object.get("response", None) if response == "ok": self.login_server_record = JSON_object.get("loginserver_record", None) database.addLoginServerRecord(self.username, self.login_server_record) return 0 else: return 1
def getUsers(self): headers = self.createAuthorisedHeader(True) url = "http://cs302.kiwi.land/api/list_users" JSON_object = helper.postJson(None, headers, url) response = JSON_object.get("response", None) if response == 'ok': self.users = JSON_object.get("users", None) if self.users is not None: self.loadUsersIntoDatabase(self.users) return 0 else: return 1
def sendBroadcastMessage(self, message): headers = self.createAuthorisedHeader(False) ud = database.getUserHashes(self.username) loginserver_record = ud.get("loginrecord") ts = str(time.time()) message_bytes = bytes(loginserver_record+message+ts, encoding='utf-8') signed = self.signing_key.sign(message_bytes, encoder=nacl.encoding.HexEncoder) signature_hex_str = signed.signature.decode('utf-8') payload = { "loginserver_record": loginserver_record, "message": message, "sender_created_at": ts, "signature": signature_hex_str } try: username, pubkey, server_time, signature_str = helper.breakLoginRecord(loginserver_record) except Exception as e: print(e) return 1 isMeta =re.search("^!(M|m)eta:", message) if not isMeta: database.addBroadCast(loginserver_record, message, ts, signature_hex_str, username, 'false') else: database.addBroadCast(loginserver_record, message, ts, signature_hex_str, username, 'true') all_users = database.getAllUsers() for user in all_users: user_address = user.get("address", None) user_status = user.get("status", None) if user_address is None or user_status != "online": continue url = "http://" + user_address + "/api/rx_broadcast" if user.get("username") == 'admin': url = "http://cs302.kiwi.land/api/rx_broadcast" try: JSON_object = helper.postJson(payload, headers, url) print(JSON_object) response = JSON_object.get("response", None) if response == "ok": print("broadcast successfully sent") else: print("response not OK") except: print("FAILED TO BROADCAST to url " + str(url))
def retrieveOfflineData(self, since): headers = self.createAuthorisedHeader(False) all_users = database.getAllUsers() for user in all_users: user_address = user.get("address", None) user_status = user.get("status", None) if user_address is None or user_status != "online": continue url = "http://" + user_address + "/api/rx_checkmessages?since=" + since print(url) try: JSON_object = helper.postJson(None, headers, url) except Exception as e: print("cannot retrieveOfflineData from " + str(url)) print(e) else: response = JSON_object.get("response", None) if response == "ok": broadcasts = JSON_object.get("broadcasts", []) private_messages = JSON_object.get("private_messages", []) for broadcast in broadcasts: loginserver_record = broadcast.get("loginserver_record", None) if not loginserver_record: continue message = broadcast.get("message", None) username, pubkey, server_time, signature_str = helper.breakLoginRecord(loginserver_record) isMeta = re.search("^!Meta:(\w+):(\w+)", message) if not isMeta: database.addBroadCast(broadcast.get("loginserver_record", None), broadcast.get("message", None), broadcast.get("sender_created_at", None), broadcast.get("signature", None), username, 'false') else: database.addBroadCast(broadcast.get("loginserver_record", None), broadcast.get("message", None), broadcast.get("sender_created_at", None), broadcast.get("signature", None), username, 'true') key = isMeta.group(1) val = isMeta.group(2) helper.addMetaData(key,val,username) for pm in private_messages: loginserver_record = broadcast.get("loginserver_record", None) if not loginserver_record: continue username, pubkey, server_time, signature_str = helper.breakLoginRecord(loginserver_record) database.addReceivedMessage(pm.get("target_username", None), pm.get("target_pubkey", None), pm.get("encrypted_message", None), pm.get("sender_created_at", None), pm.get("signature", None), username, loginserver_record, 'false') else: print("response not OK")
def addPrivateData(self, private_data): url_add = "http://cs302.kiwi.land/api/add_privatedata" headers = self.createAuthorisedHeader(True) ts = str(time.time()) private_data_str = json.dumps(private_data) key = helper.getSymmetricKeyFromPassword(self.password2) private_data_encr = helper.encryptStringKey( key, private_data_str) #encrypted private data private_data_hex_str = base64.b64encode(private_data_encr).decode( 'utf-8') #hexed private data print(len(private_data_hex_str)) if len(private_data_hex_str) >= 4096: print("length of pd exceeds") self.clearPrivateData() return #creating message and then signed message_bytes = bytes(private_data_hex_str + self.login_server_record + ts, encoding='utf-8') signed = self.signing_key.sign(message_bytes, encoder=nacl.encoding.HexEncoder) signature_hex_str = signed.signature.decode('utf-8') payload = { "privatedata": private_data_hex_str, "loginserver_record": self.login_server_record, "client_saved_at": ts, "signature": signature_hex_str } try: JSON_object = helper.postJson(payload, headers, url_add) response = JSON_object.get("response", None) if response == "ok": print("added to private data successfully!") return 0 else: raise Exception("failed to save private datta") except Exception as e: print(e) return 1
def addPublicKey(self): url = "http://cs302.kiwi.land/api/add_pubkey" # Generate a new random signing key hex_key = nacl.signing.SigningKey.generate().encode( encoder=nacl.encoding.HexEncoder) signing_key = nacl.signing.SigningKey(hex_key, encoder=nacl.encoding.HexEncoder) # dealing with public keys pubkey = signing_key.verify_key pubkey_hex = pubkey.encode(encoder=nacl.encoding.HexEncoder) pubkey_hex_str = pubkey_hex.decode('utf-8') #creating message and then signed message_bytes = bytes(pubkey_hex_str + self.username, encoding='utf-8') signed = signing_key.sign(message_bytes, encoder=nacl.encoding.HexEncoder) signature_hex_str = signed.signature.decode('utf-8') headers = self.createAuthorisedHeader(True) payload = { "pubkey": pubkey_hex_str, "username": self.username, "signature": signature_hex_str } JSON_object = helper.postJson(payload, headers, url) response = JSON_object.get("response", None) login_server_record = JSON_object.get("loginserver_record", None) if response == "ok" and login_server_record is not None: print("pubkey added successfully!") self.signing_key = signing_key self.hex_key = hex_key self.login_server_record = login_server_record #database.addLoginServerRecord(self.username, login_server_record) return 0 else: print("Failed to add pubkey") return 1
def getNewApiKey(self): url = "http://cs302.kiwi.land/api/load_new_apikey" headers = self.createAuthorisedHeader(True) try: JSON_object = helper.postJson(None, headers, url) response = JSON_object.get("response", None) if response == "ok": apikey = JSON_object.get("api_key", None) self.apikey = apikey if not apikey or response != "ok": print("NO API KEY") return 1 except Exception as e: print(e) return 1 #filename = "tmp/api.txt" #os.makedirs(os.path.dirname(filename), exist_ok=True) #with open(filename, "w") as f: #f.write(apikey) return 0
def sendGroupMessage(self, target_group_hash, message): headers = self.createAuthorisedHeader(False) target_group_bytes = bytes(target_group_hash, encoding='utf-8') try: key = helper.getEncryptionKey(self.logserv,target_group_bytes) except Exception as e: print(e) return 1 if not key: print("ERROR IN SENDING MESSAGE") return 1 try: encr_message = helper.encryptStringKey(key, message).hex() #TODO change if hex is appropriate. except Exception as e: print(e) return 1 #encr_message = helper.encryptMessage(message, user_pubkey) ud = database.getUserHashes(self.username) loginserver_record = ud.get("loginrecord") ts = str(time.time()) message_bytes = bytes(loginserver_record+encr_message+ts, encoding='utf-8') signed = self.signing_key.sign(message_bytes, encoder=nacl.encoding.HexEncoder) signature_hex_str = signed.signature.decode('utf-8') payload = { "loginserver_record": loginserver_record, "groupkey_hash": target_group_hash, "group_message": encr_message, "sender_created_at": ts, "signature": signature_hex_str } pubkey_hex = self.signing_key.verify_key.encode(encoder=nacl.encoding.HexEncoder) try: self_encrypted_message = helper.encryptMessage(message, pubkey_hex) except Exception as e: print("failed to encrypt sent message.") print(e) return 1 print(target_group_hash) target_users = database.getGroupUsers(target_group_hash) database.addsentMessages(self.username, target_group_hash, self_encrypted_message, ts, "group") for tg in target_users: username = tg.get("username") user = database.getUserData(username) user_address = user.get("address", None) user_status = user.get("status", None) if user_address is None or user_status != "online": continue url = "http://" + user_address + "/api/rx_groupmessage" print(url) try: JSON_object = helper.postJson(payload, headers, url) print(JSON_object) response = JSON_object.get("response", None) if response == "ok": print("message sent") print("url") else: print("response not OK") except: print("FAILED TO sent group message!")
def createGroupChatP2p(self, target_usernames): headers = self.createAuthorisedHeader(False) print("creating group chats") error = 0 #generating symmetric keys to be stored key = helper.generateRandomSymmetricKey() key_str = key.hex() try: helper.addToPrivateData(self.logserv, "prikeys", key_str) except Exception as e: print(e) return 1 #create a group invite ud = database.getUserHashes(self.username) loginserver_record = ud.get("loginrecord") try: groupkey_hash = helper.getShaHash(key) except Exception as e: print(e) return 1 groupkey_hash_str = groupkey_hash.decode('utf-8') database.addGroupChatReceived(groupkey_hash_str, self.username) #encr = helper.getEncryptionKey(self.logserv, groupkey_hash) for username in target_usernames: user = database.getUserData(username) user_address = user.get("address", None) user_location = user.get("location", None) user_pubkey = user.get("pubkey", None) try: encr_groupkey = helper.encryptMessage(key, user_pubkey) except Exception as e: print(e) return 1 ts = str(time.time()) message_bytes = bytes(loginserver_record+groupkey_hash_str+user_pubkey+username+encr_groupkey+ts, encoding='utf-8') signed = self.signing_key.sign(message_bytes, encoder=nacl.encoding.HexEncoder) signature_hex_str = signed.signature.decode('utf-8') payload = { "loginserver_record": loginserver_record, "groupkey_hash": groupkey_hash_str, "target_pubkey": user_pubkey, "target_username": username, "encrypted_groupkey": encr_groupkey, "sender_created_at": ts, "signature": signature_hex_str } if user_address is None: continue url = "http://" + user_address + "/api/rx_groupinvite" print(url) try: JSON_object = helper.postJson(payload, headers, url) print(JSON_object) response = JSON_object.get("response", None) if response == "ok": print("group invite sent successfully") database.addGroupChatReceived(groupkey_hash_str, username) else: print("response not OK") except Exception as e: print("FAILED TO SEND!") print(e) error = 1 return error, groupkey_hash_str
def sendPrivateMessage(self, message, send_user): headers = self.createAuthorisedHeader(False) user = database.getUserData(send_user) user_address = user.get("address", None) user_pubkey = user.get("pubkey", None) user_status = user.get("status", None) try: encr_message = helper.encryptMessage(message, user_pubkey) except Exception as e: print(e) print("failed to encrypt message") return 1 ud = database.getUserHashes(self.username) loginserver_record = ud.get("loginrecord") ts = str(time.time()) message_bytes = bytes(loginserver_record+user_pubkey+send_user+encr_message+ts, encoding='utf-8') signed = self.signing_key.sign(message_bytes, encoder=nacl.encoding.HexEncoder) signature_hex_str = signed.signature.decode('utf-8') pubkey_hex = self.signing_key.verify_key.encode(encoder=nacl.encoding.HexEncoder) try: self_encrypted_message = helper.encryptMessage(message, pubkey_hex) except Exception as e: print("failed to encrypt sent message.") print(e) return 1 msg = database.addsentMessages(self.username, send_user, self_encrypted_message, ts, "user") if msg["response"] == "error": return 1 payload = { "loginserver_record": loginserver_record, "target_pubkey": user_pubkey, "encrypted_message": encr_message, "target_username": send_user, "sender_created_at": ts, "signature": signature_hex_str } if user_status == "online": user = database.getUserData(send_user) user_address = user.get("address", None) user_status = user.get("status", None) url = "http://" + user_address + "/api/rx_privatemessage" try: JSON_object = helper.postJson(payload, headers, url) response = JSON_object.get("response", None) if response == "ok": print("pm sent successfully") return 0 else: raise Exception("error sending private message") except Exception as e: print("FAILED TO SEND MESAGE") print(e) all_users = database.getAllUsers() #sending offline message. for user in all_users: user_address = user.get("address", None) user_status = user.get("status", None) if user_address is None or user_status != "online": continue url = "http://" + user_address + "/api/rx_privatemessage" try: JSON_object = helper.postJson(payload, headers, url) response = JSON_object.get("response", None) if response == "ok": print("pm sent successfully sent") else: raise Exception("error sending private message") except Exception as e: print(e)