From a66014a22bf735b56fc1f88da97c325a72fa1200 Mon Sep 17 00:00:00 2001 From: Votre Nom Date: Tue, 12 Nov 2019 12:57:54 +0100 Subject: [PATCH] Prepared Session managment --- .clients_keys | 5 ++ .hosts_keys | 2 + client_test_3.py | 4 +- server_test_3.py | 50 ++++++++++++++++-- utils/rsa_tenamortech_utils.py | 10 ++++ utils/symmetric_keys_manager_1.py | 86 +++++++++++++++++++++++++++---- 6 files changed, 141 insertions(+), 16 deletions(-) create mode 100644 .clients_keys create mode 100644 .hosts_keys diff --git a/.clients_keys b/.clients_keys new file mode 100644 index 0000000..5010206 --- /dev/null +++ b/.clients_keys @@ -0,0 +1,5 @@ +d7d7a7d2-b080-437a-8f05-6c4b3f763efb 63vBualsYMEwx-9U5MF9D83gs8BgW6M0U1h-Vx-78KI= 0 +b544fb5d-f779-4cc1-92d5-b7d9b6d1e739 PutsEcWM9C16j3jXgxHRMsc4IYbN9fIwmiLd-koc0_Y= 0 +4529ae1f-8ffc-42eb-b9b6-d1d4225b1607 EjrlAzFKCE1QeLrLBjtr3nhgpk7YCEmE7KRlUoilxsg= 0 +26c9f89a-f8e1-4b22-83bd-417c5047e527 3Po3ppCKsxBbCxsfueFxnSu_IzuXR17mC4Mw8ybfGtE= 0 +73e129a2-461b-40ef-a97c-a059a664a08e DHXNwpBPUp6CQ4ePvKm04z5a4EE2hSCpz6Nd7oyNe18= 0 diff --git a/.hosts_keys b/.hosts_keys new file mode 100644 index 0000000..d43d1d5 --- /dev/null +++ b/.hosts_keys @@ -0,0 +1,2 @@ +0cb49300-4614-41e2-aeaa-f6dfaf03e432 b'I33_0mixgFEvJw68y9FazyncoLz7b1MgCKExlWy6y5w=' 00ac41cc2-eb50-46d0-967e-a0aa22024c3a 985078ec-30ba-450e-a830-d082f75853b8 75060f8f-abc5-4231-b3ed-7097dee2b24d msBo4XZecSUDHDzgeSizBCaOINrd_rXNg3_Yg9WhWek= f5ba9849-1bdb-4d5e-a00b-087335c4ecdf En5PGW1gsbFe94QD1r9tZyEAI6nUtgY4cg1fDZQzFSc= 073511230-8b8d-4bc8-90fc-6183500b6987 6BVGnUx_H1DgyFuyb3cvm0rb7bdKtqF-c_3TEuZV1w8= 0 +fb0739c2-1872-48b9-9f7f-5a6f739dc9ed zOvyDD4shPk3CeekXa5oLreRcQShl2yspg0s5-7ARQI= 0 diff --git a/client_test_3.py b/client_test_3.py index 26e9bd5..bcc1efc 100644 --- a/client_test_3.py +++ b/client_test_3.py @@ -34,10 +34,10 @@ while MESSAGE != 'exit': got_pub_key_server = True # Now we have the pub key of the server, we will send our pub key too #encrypted_public_key = encrypt_msg(public_key_pem, public_key_server) - encrypted_public_key = encrypt_msg(bytes("test123456789000000000000000000000000000iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii000", 'utf-8'), public_key_server) + #encrypted_public_key = encrypt_msg(bytes("test123456789000000000000000000000000000iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii000", 'utf-8'), public_key_server) print("Server public key received") print("Sending current client public key [ ... ] ") - tcpClientA.send(encrypted_public_key) + tcpClientA.send(public_key_pem) print("Sending current client public key [ OK ] ") else: diff --git a/server_test_3.py b/server_test_3.py index 864de72..12968fa 100644 --- a/server_test_3.py +++ b/server_test_3.py @@ -2,13 +2,17 @@ import socket from threading import Thread from socketserver import ThreadingMixIn from utils.keys_manager_1 import * - +from utils.symmetric_keys_manager_1 import * # --- Init keys --- () +def de_serialize_pub_key(public_key_pem): + return serialization.load_pem_public_key(public_key_pem,backend=default_backend()) + # Multithreaded Python server : TCP Server Socket Thread Pool -class ClientThread(Thread): - +class ClientThread(Thread): + got_pub_key_client = False + able_to_retrieve_session_id = False def __init__(self,ip,port, private_key, public_key): Thread.__init__(self) self.ip = ip @@ -20,7 +24,45 @@ class ClientThread(Thread): def run(self): while True : - data = conn.recv(2048) + data = conn.recv(2048) + if not got_pub_key_client: # we might receive a pub_key in clear, or an encrtpted session_id + print("[DEBUG] Waiting for HandShake [ ... ]" + # --- Text was clear and client sent pub_key + if "-----BEGIN PUBLIC KEY-----" in data: + print("[DEBUG] Received Public Key from Client [ OK ]") + public_key_client = de_serialize_pub_key(data) + got_pub_key_client = True + # --- Decrypt data and try to load session_id etc + else: + print("[DEBUG] No HandShake, got SessionID from Client") + print("[DEBUG] Waiting for SessionID validation [ ... ]") + msg = decrypt_msg(data, private_key) + if(len(msg) == 36): # SessionID length should be 36 char. + print("[DEBUG] SessionID format looks correct [ ~ ]") + session_id = msg + (symmetric_key,client_pub_key) = reload_session_sym_key(session_id) + + # --- Unable to retrieve sessionID and public Key was not sent + # --- Abort connection now + if(symmetric_key == -1): + print("[DEBUG] Waiting for SessionID validation [ FAIL ]") + print("[DEBUG] Invalid SessionID, will now abort negociation [ FAIL ]") + break + else: + able_to_retrieve_session_id = True + print("[DEBUG] Waiting for SessionID validation [ OK ]") + print("[DEBUG] SessionID is valid, symmetric_key and current Client Public key were retrieved successfully") + print("[DEBUG] I'm all yours... [ :) ]") + # --- SessionID that the client sent is valid, we got all the required infos + # --- Client sent did not send sessionID but sent his public Key + # --- Create a new session for it, (gen sessionID, create new symmetric Key, store his public key) + if able_to_retrieve_session_id == False: + print("[DEBUG] No existing Session, will now initiate new Session [ ... ]") + # --- This function will create a sessionID, return a symmetric key and store the pub key + symmetric_key = gen_sym_key_and_save(public_key_client) + print("[DEBUG] No existing Session, will now initiate new Session [ OK ]") + print("[DEBUG] I'm all yours... [ :) ]") + print("Server received data:", data) MESSAGE = input("Multithreaded Python server : Enter Response from Server/Enter exit:").encode('utf-8') if MESSAGE == 'exit': diff --git a/utils/rsa_tenamortech_utils.py b/utils/rsa_tenamortech_utils.py index 964780f..020b5ff 100644 --- a/utils/rsa_tenamortech_utils.py +++ b/utils/rsa_tenamortech_utils.py @@ -105,3 +105,13 @@ def encrypt_msg(msg,public_key): ) return enc_msg +def decrypt_msg(enc_msg,private_key): + msg = private_key.decrypt( + enc_msg, + padding.OAEP( + mgf=padding.MGF1(algorithm=hashes.SHA256()), + algorithm=hashes.SHA256(), + label=None + ) + ) + return msg diff --git a/utils/symmetric_keys_manager_1.py b/utils/symmetric_keys_manager_1.py index 029fe99..49988aa 100644 --- a/utils/symmetric_keys_manager_1.py +++ b/utils/symmetric_keys_manager_1.py @@ -1,19 +1,85 @@ # Symmetric crypto lib from cryptography.fernet import Fernet -key = Fernet.generate_key() +#UniqueID +import uuid -file = open('key.key', 'wb') -file.write(key) # The key is type bytes still -file.close() -message = "my deep dark secret".encode() +def gen_rand_session_id(): + return str(uuid.uuid4()) -f = Fernet(key) -encrypted = f.encrypt(message) +def gen_sym_key_and_save(client_pub_key): + key = Fernet.generate_key() -print(encrypted) + root_file_path = '.auth_server_test/' + path = root_file_path + 'server' + path_clients_pub_keys = root_file_path + 'server/clients_pub_keys' -decrypted = f.decrypt(encrypted) + session_id = gen_rand_session_id() + + file = open('.clients_keys', 'ab') # changed from 'wb' to 'w+' ... + file.write((session_id + " ").encode('utf-8')) + file.write(key + (" ").encode('utf-8')) # The key is type bytes still + file.write(('0\n').encode('utf-8')) + file.close() -print(decrypted) + # --- Store the client public Key for next time. + # --- Public keys are stored in '.auth_server_test/server/clients_pub_keys/session_id.pub' + keys_dir_path = Path.home() / path_client_pub_keys + # Path exists ? If not we will create it + keys_dir_path.mkdir(exist_ok=True) + + key_pem = public_key_serializer(key) + key_path = keys_dir_path / str(session_id) + '.pub' + + with open(str(key_path), 'wb') as f: + f.write(client_pub_key) + + return key + +def reload_session_sym_key(sessionid): + root_file_path = '.auth_server_test/' + path = root_file_path + 'server/' + path_clients_pub_keys = path + 'clients_pub_keys/' + filename='.clients_keys' + + session_id_found = False + + # --- Open session file + with open(filename) as f: + line = f.readline().rstrip() + while(line and session_id_found == False): + # each line contains (session_id, sym_key, sym_key_nb_use) + # Those infos are spaced with "space" char, so we use 'split' fuction to get an array + cur_client_infos = line.split() + # If we find the given sessionID: + if(cur_client_infos[0] == sessionid): # cur_client_info[0] is the session_id stored in the cur line + session_id_found = True + line = f.readline().rstrip() + + # --- We found the given sessionID, so we will now load the corresponding client public key we previously stored. + if session_id_found == True: + with open(str(path_clients_pub_keys + cur_client_infos[0] + '.pub'), "rb") as key_file: + client_pub_key_pem = serialization.load_pem_public_key( + key_file.read(), + backend=default_backend() + ) + # --- Return the Symmetric Key used with this client and the PEM formated client public Key + return (cur_client_infos[1],client_pub_key_pem) + else: + # Return Error tuple + return (-1,'') + +def encrypt_msg_symmetric(msg, key): + msg = msg.encode() + f_key = Fernet(key) + enc_msg = f_key.encrypt(msg) + +#print(encrypted) + +#decrypted = f.decrypt(encrypted) + +#print(decrypted) + +#gen_sym_key_and_save() +print(reload_session_sym_key("26c9f89a-f8e1-4b22-83bd-417c5047e527"))