def test_hmac_b64(self): key_one = Crypto_Functions.generate_session_key() key_two = Crypto_Functions.generate_session_key() msg = b"Hello There" # Correct tag = Crypto_Functions.hmac_b64(msg, key_one) tag = base64.b64decode(tag) self.assertTrue(Crypto_Functions.check_hmac_b64(msg, tag, key_one)) # Incorrect tag = Crypto_Functions.hmac_b64(msg, key_two) tag = base64.b64decode(tag) self.assertFalse(Crypto_Functions.check_hmac_b64(msg, tag, key_one)) tag = Crypto_Functions.hmac_b64(msg, key_one) tag = base64.b64decode(tag) self.assertFalse( Crypto_Functions.check_hmac_b64(b"Hello", tag, key_one))
def send_group_handshake(self, group_name, group_members): """ Same as send_handshake() but handles sending to mulitple members and providing the correct information """ # Initialize the group dict self.groups[group_name] = {} self.groups[group_name]["members"] = group_members # Send a handshake to each member in the group key = Crypto_Functions.generate_session_key() for recipient in group_members: # Make sure we have a public key if recipient not in self.contacts.keys( ) or "public_key" not in self.contacts[recipient]: self.populate_public_keys(recipient) keys = Send.send_group_handshake( self.username, recipient, group_members, self.s, self.private_key, self.contacts[recipient]["public_key"], key, group_name) self.groups[group_name]["aes_key"] = keys["aes"] self.groups[group_name]["hmac_key"] = keys["hmac"] email = self.username group_aes = base64.b64encode(self.groups[group_name]["aes_key"]) enc_group_aes, iv_aes = Crypto_Functions.aes_encrypt( str(group_aes), self.password_aes) enc_group_aes = str(base64.b64encode(enc_group_aes)) iv_aes = str(base64.b64encode(iv_aes)) # Get encrypted hmac under self.password_aes hmac_key = base64.b64encode(self.groups[group_name]["hmac_key"]) enc_hmac_key, iv_hmac = Crypto_Functions.aes_encrypt( str(hmac_key), self.password_aes) enc_hmac_key = str(base64.b64encode(enc_hmac_key)) iv_hmac = str(base64.b64encode(iv_hmac)) for member in group_members: contact = member # Create the signature signature_contents = email + contact + enc_group_aes + enc_hmac_key + iv_aes + iv_hmac # signature_contents) signature = str( Crypto_Functions.hmac_b64(signature_contents.encode(), self.password_hmac)) Database.add_group(self.username, group_name, member, signature, enc_group_aes, iv_aes, enc_hmac_key, iv_hmac)
def send_direct_handshake(self, recipient): """ Sends a handshake to the recipient to establish secure channels. Also updates the contact information """ # Send handshake keys = Send.send_direct_handshake( self.username, recipient, self.s, self.private_key, self.contacts[recipient]["public_key"]) # Update recipient's keys self.contacts[recipient]["aes_key"] = keys["aes"] self.contacts[recipient]["hmac_key"] = keys["hmac"] email = self.username contact = recipient # Get encrypted aes under self.password_aes contact_aes = base64.b64encode(keys["aes"]) enc_contact_aes, iv_aes = Crypto_Functions.aes_encrypt( str(contact_aes), self.password_aes) enc_contact_aes = str(base64.b64encode(enc_contact_aes)) iv_aes = str(base64.b64encode(iv_aes)) # Get encrypted hmac under self.password_aes hmac_key = base64.b64encode(keys["hmac"]) enc_hmac_key, iv_hmac = Crypto_Functions.aes_encrypt( str(hmac_key), self.password_aes) enc_hmac_key = str(base64.b64encode(enc_hmac_key)) iv_hmac = str(base64.b64encode(iv_hmac)) # Create the signature signature_contents = self.username + contact + enc_contact_aes + enc_hmac_key + iv_aes + iv_hmac signature = str( Crypto_Functions.hmac_b64(signature_contents.encode(), self.password_hmac)) # Update the database Database.add_contact_info(email, contact, enc_contact_aes, signature, iv_aes, enc_hmac_key, iv_hmac)
def send_direct(sender, recipient, contacts, message, s): """ Sends an encrypted direct message to the recipient. """ # Get keys aes_key = contacts[recipient]["aes_key"] hmac_key = contacts[recipient]["hmac_key"] # Encrypt enc_msg, iv = Crypto_Functions.aes_encrypt(message, aes_key) # Create message tag on encypted data timestamp = str(datetime.datetime.now().timestamp()) tag_contents = str(base64.b64encode(enc_msg)) + timestamp tag = Crypto_Functions.hmac_b64(tag_contents.encode(), hmac_key) # Encoding enc_msg_b64 = base64.b64encode(enc_msg) iv_b64 = base64.b64encode(iv) s.send(Requests.direct_message(sender, recipient, str(enc_msg_b64), str(iv_b64), timestamp, str(tag)))
def send_group_message(message, sender, group_name, s, group_members, groups): """ Send a message to each member in the group. This is done through one send request """ # Get shared key aes_key = groups[group_name]["aes_key"] hmac_key = groups[group_name]["hmac_key"] # Encrypt enc_msg, iv = Crypto_Functions.aes_encrypt(message, aes_key) # Create message tag on encypted data timestamp = str(datetime.datetime.now().timestamp()) tag_contents = str(base64.b64encode(enc_msg)) + timestamp tag = Crypto_Functions.hmac_b64(tag_contents.encode(), hmac_key) # Encoding enc_msg_b64 = base64.b64encode(enc_msg) iv_b64 = base64.b64encode(iv) s.send(Requests.group_message(sender, ",".join(group_members), group_name, str(enc_msg_b64), str(iv_b64), timestamp, str(tag)))
def create_account(self): valid_username = False while not valid_username: self.username = input("Enter email: ") if (Database.check_user(self.username)): print("Username already exists in the system.") else: valid_username = True # Here for email verification valid_email = False while not valid_email: email = self.username print(email) if not self.check_email_valid(email): print("Email entered not valid") self.create_account() else: request = Requests.send_email(email) self.ca.send(request) code = input( "Please enter the verification code sent to your email address: " ) request2 = Requests.verify_email(code) self.ca.send(request2) data = self.ca.recv(4096) request = Requests.parse_request(data) if request.is_ca_response_email_valid(): print("Authentication was successful") valid_email = True elif request.is_ca_response_email_invalid(): print("Code was not valid. Please try again.") strong_password = False while not strong_password: password = input("Create new password: "******"Waiting for CA...") data = self.ca.recv(4096) request = Requests.parse_request(data) if len(request.data) == 0: print( "There was in issue with the received data. Received the following raw data: ", data) elif request.is_ca_response_valid(): print("Received a valid response from CA.") print("Sending account information to the server.") username = request.data["username"] public_key = request.data["public_key"] ca_signature = request.data["signature"] request = Requests.create_new_account( username, public_key, ca_signature) private_key_b64 = base64.b64encode(self.private_key) enc_private_key, aes_iv = Crypto_Functions.aes_encrypt( str(private_key_b64), self.password_aes) enc_private_key_b64 = base64.b64encode(enc_private_key) aes_iv_b64 = base64.b64encode(aes_iv) tag_contents = str(enc_private_key_b64) + str( aes_iv_b64) hmac = Crypto_Functions.hmac_b64( tag_contents.encode(), self.password_hmac) hmac_b64 = hmac Database.add_user_account(self.username, str(enc_private_key_b64), str(aes_iv_b64), str(hmac_b64)) self.s.send(request) break elif request.is_ca_response_invalid(): print( "CA indicated an invalid request. Please try again with a different username." ) self.create_account() break # When we get to this point, we know CA sent back a valid response and that we sent a request # to the server to create an account. Now we wait for the server to send a confirmation that # the account has been created. while True: print("Waiting for the server...") data = self.s.recv(4096) request = Requests.parse_request(data) if len(request.data) == 0: print( "There was in issue with the received data. Received the following raw data: ", data) elif request.is_account_created(): print( "Account successfully created! Please log in with your new credentials." ) break elif request.is_account_not_created(): print("Account was not created. Please try again.") self.create_account() else: print( "The password you typed was not secure. Password must use letters and numbers and must be at least 8 characters." ) # When we get to this point, we know that the user's account has been created and we prompt the user to login # with their new credentials to proceed. self.login()
def handle_receive(self): """ Handles all of the different receiving requests from server """ while True: data = self.s.recv(4096) request = Requests.parse_request(data) with self.console_lock: # Handle different message types if request.is_direct_message(): Receive.receive_direct(request.data, self.contacts, self.received_timestamps) elif request.is_group_message(): Receive.receive_group(request.data, self.groups, self.received_timestamps) elif request.is_broadcast(): print(request.data["message"]) # Initiate the group chat and save keys elif request.is_initiate_group_chat(): print("Initiating new group chat...") requester = request.data["requester"] # Make sure we have the contact if requester not in self.contacts or "public_key" not in self.contacts[ requester].keys(): self.populate_public_keys(requester) # Recieve the handshake keys = Receive.receive_group_handshake( request.data, self.username, self.groups, self.contacts, self.private_key) group_name = keys["group_name"] aes_key = keys["aes"] hmac_key = keys["hmac"] members = keys["members"] # This will completely overwrite or add a new one self.groups[group_name] = { "aes_key": aes_key, "hmac_key": hmac_key, "members": members } email = self.username # Get encrypted aes under self.password_aes group_aes = str(base64.b64encode(aes_key)) enc_goup_aes, iv_aes = Crypto_Functions.aes_encrypt( group_aes, self.password_aes) enc_goup_aes = str(base64.b64encode(enc_goup_aes)) iv_aes = str(base64.b64encode(iv_aes)) # get encrypted hmac under self.password_aes hmac_key = str(base64.b64encode(hmac_key)) enc_hmac_key, iv_hmac = Crypto_Functions.aes_encrypt( hmac_key, self.password_aes) enc_hmac_key = str(base64.b64encode(enc_hmac_key)) iv_hmac = str(base64.b64encode(iv_hmac)) # Add line for each member for member in members: contact = member signature_contents = email + contact + enc_goup_aes + enc_hmac_key + iv_aes + iv_hmac signature = str( Crypto_Functions.hmac_b64( signature_contents.encode(), self.password_hmac)) Database.add_group(self.username, group_name, contact, signature, enc_goup_aes, iv_aes, enc_hmac_key, iv_hmac) elif request.is_initiate_direct_message(): requester = request.data["requester"] if requester not in self.contacts: self.populate_public_keys(requester) keys = Receive.receive_direct_handshake( request.data, self.contacts, self.contacts[requester]["public_key"], self.private_key) aes_key = keys["aes"] hmac_key = keys["hmac"] # This will add or overwrite two fields to the requester's contact, leaving the others self.contacts[requester]["aes_key"] = aes_key self.contacts[requester]["hmac_key"] = hmac_key email = self.username contact = requester # Get encrypted aes under self.password_aes contact_aes = str(base64.b64encode(aes_key)) enc_contact_aes, iv_aes = Crypto_Functions.aes_encrypt( contact_aes, self.password_aes) enc_contact_aes = str(base64.b64encode(enc_contact_aes)) iv_aes = str(base64.b64encode(iv_aes)) # Get encrypted hmac under self.password_aes hmac_key = str(base64.b64encode(hmac_key)) enc_hmac_key, iv_hmac = Crypto_Functions.aes_encrypt( hmac_key, self.password_aes) enc_hmac_key = str(base64.b64encode(enc_hmac_key)) iv_hmac = str(base64.b64encode(iv_hmac)) # Create the signature signature_contents = self.username + contact + enc_contact_aes + enc_hmac_key + iv_aes + iv_hmac signature = str( Crypto_Functions.hmac_b64(signature_contents.encode(), self.password_hmac)) Database.add_contact_info(email, contact, enc_contact_aes, signature, iv_aes, enc_hmac_key, iv_hmac)