diff --git a/RFC8497.md b/RFC8497.md index 192e5ef..8912d78 100644 --- a/RFC8497.md +++ b/RFC8497.md @@ -141,7 +141,7 @@ Communication entre un client et un noeud ###### En-tête ###### EICP2P2 V1 - type: register + type: register_client ###### Contenu ###### @@ -160,11 +160,11 @@ Cette requête est envoyée par un client pour s'enregistrer sur le réseau. Le ###### Contenu ###### - id_noeud::id_client + id_noeud{%=&%&=%}id_client ###### Utilisation ###### -Réponse à un `register`. Le noeud communique au client son id et l'id du noeud auquel il est connecté. +Réponse à un `register_client`. Le noeud communique au client son id et l'id du noeud auquel il est connecté. ### Send ### @@ -191,7 +191,7 @@ Cette requête est envoyé par un client enregistré à un noeud pour envoyer un ###### Contenu ###### - Rien + Rien/Erreur client incunnu ###### Utilisation ###### @@ -217,6 +217,28 @@ Cette requête est envoyée par le destinataire d'une requête `send` après avo Envoyé par le client pour se déconnecter du réseau. Ne demande aucune réponse de la part du noeud. +### Get users ### + +###### En-tête ###### + + EICP2P2 V1 + type: getUsers + +###### Contenu ###### + + Rien + +### Get User ACK ### + +###### En-tête ###### + + EICP2P2 V1 + type: getUsersACK + +###### Contenu ###### + + Listedesutilisateurs + ### Ping ### ###### En-tête ###### diff --git a/client/main.py b/client/main.py index 1f96cbe..f2df546 100644 --- a/client/main.py +++ b/client/main.py @@ -18,10 +18,41 @@ try: except ModuleNotFoundError: # Pycryptodomex from Cryptodome.PublicKey import RSA as RSA from Cryptodome.Cipher import PKCS1_OAEP as PKCS1_OAEP + from Cryptodome.Cipher import AES as AES pycryptodome = True +class RsaGenThread(threading.Thread): + + def __init__(self, client_, difficulty=2): + threading.Thread.__init__(self) + self.client = client_ + self.difficulty = difficulty + + def run(self): + if os.path.isfile("private.pem"): + try: + with open("private.pem", "rb") as keyfile: + rsa = RSA.importKey(keyfile.read()) + if not rsa.has_private(): + warning("Le fichier clef ne contient pas de clef privée") + raise ValueError + self.client.rsa = rsa + except (IndexError, ValueError): + warning("Fichier clef corrompu") + debug("Suppression du fichier clef corromu") + os.remove("private.pem") + if not os.path.isfile("private.pem"): # We're not using if/else because we may delete the file in the + # previous if statement + debug("Génération de la clef RSA pour %s" % self.client.name) + self.client.rsa = RSA.generate(BUFFER_SIZE + 256 * self.difficulty) + with open("private.pem", "wb") as keyfile: + keyfile.write(self.client.rsa.exportKey()) + with open("public.pem", "wb") as keyfile: + keyfile.write(self.client.rsa.publickey().exportKey()) + + def setup_logging(default_path='log_config.json', default_level=logging.INFO, env_key='LOG_CFG'): """Setup logging configuration """ @@ -58,8 +89,8 @@ NAME = b"client1" VERSION = b"EICP2P2 V1" REQUEST_TYPE = [ - b'ping', b'pingACK', b'updateAsk', b'updateBack', b'transfer', b'register', b'registerACK', b'send', b'sendACK', - b'exit', b'RSASend', b'init', + b'ping', b'pingACK', b'updateAsk', b'updateBack', b'transfer', b'register_client', b'registerACK', b'send', b'sendACK', + b'exit', b'RSASend', b'init', b'getUsers', b'getUsersACK', ] clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) @@ -77,20 +108,38 @@ class MainThread(threading.Thread): self.rsa = None self.aes_key = None self.clientSocket = None + self.users = {} def run(self): - rsa = self.RsaGenThread(self) + rsa = RsaGenThread(self) rsa.start() rsa.join() self.clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.clientSocket.connect((HOST, PORT)) self.initialisation() + self.register() + self.get_users() + print(self.users) + while True: + try: + type = bytes(input("Type: "), "ascii") + contenu = bytes(input("Contenu: "), "ascii") + self.send_aes(self.gen_header(type_=type)+contenu) + print(self.receive_aes()) + except Exception as e: + print(e) + + def register(self): + self.send_aes(self.gen_header(type_=b"register_client")) + self.id_noeud, self.id_client = self.receive_aes()[BUFFER_SIZE:].split(b"{%=&%&=%}") def initialisation(self): header = self.gen_header(b"RSASend", from_=b"client") content = self.rsa.publickey().exportKey() self.send(header + content) + print("oki1") data = self.receive_rsa() + print("oki2") header = self.extract_header(data[:BUFFER_SIZE]) if header[b"type"] != b"init": debug("Incorrect request type, end of connection") @@ -139,34 +188,60 @@ class MainThread(threading.Thread): header += b"\nfrom: " + from_ return header.ljust(BUFFER_SIZE, b';') - class RsaGenThread(threading.Thread): + def get_users(self): + self.send_aes(self.gen_header(type_=b'getUsers')) + back = self.receive_aes() + print(back) + header = self.extract_header(back) + contenu = back[BUFFER_SIZE:] + if header[b"type"] == b"getUsersACK": + self.users = [(contenu.split(b"%!!%")[i], i) for i in range(len(contenu.split(b"%!!%")))] - def __init__(self, client_, difficulty=2): - threading.Thread.__init__(self) - self.client = client_ - self.difficulty = difficulty + def send_aes(self, to_send, key=None): + """Send message with aes encryption - def run(self): - if os.path.isfile("private.pem"): - try: - with open("private.pem", "rb") as keyfile: - rsa = RSA.importKey(keyfile.read()) - if not rsa.has_private(): - warning("Le fichier clef ne contient pas de clef privée") - raise ValueError - self.client.rsa = rsa - except (IndexError, ValueError): - warning("Fichier clef corrompu") - debug("Suppression du fichier clef corromu") - os.remove("private.pem") - if not os.path.isfile("private.pem"): # We're not using if/else because we may delete the file in the - # previous if statement - debug("Génération de la clef RSA pour %s" % self.client.name) - self.client.rsa = RSA.generate(BUFFER_SIZE + 256 * self.difficulty) - with open("private.pem", "wb") as keyfile: - keyfile.write(self.client.rsa.exportKey()) - with open("public.pem", "wb") as keyfile: - keyfile.write(self.client.rsa.publickey().exportKey()) + :param to_send: Message to send + :type to_send: bytes + :param key: key to replace self.aes_key + :type key: bytes + + :rtype: NoneType + :return: Nothing""" + debug(b"Send with AES encryption: " + to_send) + if key is None: + key = self.aes_key + if key is None: + info("AES key not generated, connection failure.") + self.client.send(b"Error") + return + # Get RSA key + aes_object = AES.new(key, AES.MODE_ECB) + encrypted = b"" + for to_send_text in [to_send[i:i + 32] for i in range(0, len(to_send), 32)]: + encrypted += aes_object.encrypt(to_send_text.ljust(32, b"\x00")) + self.send(encrypted) + return None + + def receive_aes(self, key=None): + """Receive message with aes encryption + + :param key: key to replace self.aes_key + :type key: bytes + """ + to_decrypt = self.receive() + debug(b"Received in aes "+to_decrypt) + if key is None: + key = self.aes_key + if key is None: + info("AES key not generated, connection failure.") + self.client.send(b"Error") + return + aes_object = AES.new(key, AES.MODE_ECB) + decrypted = b"" + for block in [to_decrypt[i:i + 32] for i in range(0, len(to_decrypt), 32)]: + print(len(block)) + decrypted += aes_object.decrypt(block) + return decrypted.rstrip(b"\x00") ################################################ COMMUNICATION WITH RSA ############################################ @@ -180,7 +255,8 @@ class MainThread(threading.Thread): cipher_rsa = PKCS1_OAEP.new(recipient_key) raw = self.receive() content = b"" - for to_decrypt in [raw[i:i + self.rsa.publickey().size_in_bytes()] for i in range(0, len(raw), self.rsa.publickey().size_in_bytes())]: + for to_decrypt in [raw[i:i + self.rsa.publickey().size_in_bytes()] for i in + range(0, len(raw), self.rsa.publickey().size_in_bytes())]: content += cipher_rsa.decrypt(to_decrypt) return content diff --git a/server/main.py b/server/main.py index dfcd602..41854d1 100644 --- a/server/main.py +++ b/server/main.py @@ -13,6 +13,7 @@ try: from Crypto.PublicKey import RSA as RSA # noinspection PyUnresolvedReferences from Crypto.Cipher import PKCS1_OAEP as PKCS1_OAEP + from Crypto.Cipher import AES as AES # noinspection PyUnresolvedReferences,PyProtectedMember from Crypto.Random._UserFriendlyRNG import get_random_bytes as get_random_bytes @@ -20,6 +21,7 @@ try: except ModuleNotFoundError: # Pycryptodomex from Cryptodome.PublicKey import RSA as RSA from Cryptodome.Cipher import PKCS1_OAEP as PKCS1_OAEP + from Cryptodome.Cipher import AES as AES from Cryptodome.Random import get_random_bytes as get_random_bytes pycryptodome = True @@ -61,8 +63,8 @@ END_MESSAGE = bytes("fin".ljust(BUFFER_SIZE, ";"), "ascii") VERSION = b"EICP2P2 V1" REQUEST_TYPE = [ - b'ping', b'pingACK', b'updateAsk', b'updateBack', b'transfer', b'register', b'registerACK', b'send', b'sendACK', - b'exit', b'RSASend', b'init', + b'ping', b'pingACK', b'updateAsk', b'updateBack', b'transfer', b'register_client', b'registerACK', b'send', b'sendACK', + b'exit', b'RSASend', b'init', b'getUsers', b'getUsersACK', ] DONE = 0 @@ -77,22 +79,99 @@ main_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) main_socket.bind((HOST, PORT)) -class ServerThread(threading.Thread): - """Main server thread""" - #### Threads #### + +class RsaGenThread(threading.Thread): + + def __init__(self, difficulty=2): + threading.Thread.__init__(self) + self.difficulty = difficulty + + def run(self): + rsa = None + if os.path.isfile("private.pem"): + try: + with open("private.pem", "rb") as keyfile: + rsa = RSA.importKey(keyfile.read()) + if not rsa.has_private(): + warning("Le fichier clef ne contient pas de clef privée") + raise ValueError + except (IndexError, ValueError): + warning("Fichier clef corrompu") + debug("Suppression du fichier clef corromu") + os.remove("private.pem") + if not os.path.isfile("private.pem"): # We're not using if/else because we may delete the file in the + # previous if statement + rsa = RSA.generate(BUFFER_SIZE + 256 * self.difficulty) + with open("private.pem", "wb") as keyfile: + keyfile.write(rsa.exportKey()) + with open("public.pem", "wb") as keyfile: + keyfile.write(rsa.publickey().exportKey()) + return rsa + + +class ServerThread(threading.Thread): + """Main tread for server""" + + def __init__(self, socket, ip, port): + threading.Thread.__init__(self) # initialisation du thread + self.socket = socket + self.ip = ip + self.port = port + t = RsaGenThread() + self.rsa_key = None + if os.path.isfile("private.pem"): + try: + with open("private.pem", "rb") as keyfile: + self.rsa_key = RSA.importKey(keyfile.read()) + if not self.rsa_key.has_private(): + warning("Le fichier clef ne contient pas de clef privée") + raise ValueError + except (IndexError, ValueError): + warning("Fichier clef corrompu") + debug("Suppression du fichier clef corromu") + os.remove("private.pem") + if not os.path.isfile("private.pem"): # We're not using if/else because we may delete the file in the + # previous if statement + debug("Generate new rsa key") + self.rsa_key = RSA.generate(BUFFER_SIZE + 256 * self.difficulty) + with open("private.pem", "wb") as keyfile: + keyfile.write(self.rsa_key.exportKey()) + with open("public.pem", "wb") as keyfile: + keyfile.write(self.rsa_key.publickey().exportKey()) + debug("RSA key loaded") + self.clients = {} + self.nodes = { + self.rsa_key.publickey().exportKey(): None, + } + + def register_client(self, rsa_client, client_thread): + self.clients.update({rsa_client: (self.rsa_key, client_thread)}) + return self.rsa_key.publickey().exportKey(), rsa_client + + def send_to(self, id_dest, to_send): + if id_dest not in self.clients.keys(): + return b"Erreur client inconnu" + if self.clients[id_dest][0] is None: + return self.clients[id_dest].send_to_me(to_send) + else: + return self.nodes[self.clients[id_dest]].transfer(id_dest, to_send) + + class ClientThread(threading.Thread): """Main thread, for each client""" - def __init__(self, clientsocket, ip_client, port): + def __init__(self, clientsocket, ip_client, port, server): """Create ClientThread object :param clientsocket: Client's socket :param ip_client: Client's ip address :param port: Client's connection PORT + :param server: Server thread :type clientsocket: socket.socket :type ip_client: str :type port: int + :type server: ServerThread :return: Nothing :rtype: NoneType""" @@ -104,8 +183,9 @@ class ClientThread(threading.Thread): self.running = True self.status = None self.rsa_client = None - self.aes_key = get_random_bytes(64) + self.aes_key = get_random_bytes(32) self.type = T_NONE + self.server = server debug("Creation du thread pour %s reussie" % ip_client) def initialize(self): @@ -181,7 +261,53 @@ class ClientThread(threading.Thread): header += b"\nfrom: " + from_, return header.ljust(BUFFER_SIZE, b';') - ################################################ COMMUNICATION WITH RSA ################################################ + ################################################ COMMUNICATION WITH AES ############################################ + + def send_aes(self, to_send, key=None): + """Send message with aes encryption + + :param to_send: Message to send + :type to_send: bytes + :param key: key to replace self.aes_key + :type key: bytes + + :rtype: NoneType + :return: Nothing""" + debug(b"Send with AES encryption: " + to_send + bytes(str(self.ip), "ascii")) + if key is None: + key = self.aes_key + if key is None: + info("AES key not generated, connection failure.") + self.client.send(b"Error") + return + # Get RSA key + aes_object = AES.new(key, AES.MODE_ECB) + encrypted = b"" + for to_send_text in [to_send[i:i + 32] for i in range(0, len(to_send), 32)]: + encrypted += aes_object.encrypt(to_send_text.ljust(32, b"\x00")) + self.send(encrypted) + return None + + def receive_aes(self, key=None): + """Receive message with aes encryption + + :param key: key to replace self.aes_key + :type key: bytes + """ + to_decrypt = self.receive() + if key is None: + key = self.aes_key + if key is None: + info("AES key not generated, connection failure.") + self.client.send(b"Error") + return + aes_object = AES.new(key, AES.MODE_ECB) + decrypted = b"" + for block in [to_decrypt[i:i + 32] for i in range(0, len(to_decrypt), 32)]: + decrypted += aes_object.decrypt(block) + return decrypted.rstrip(b"\x00") + + ################################################ COMMUNICATION WITH RSA ############################################ def send_rsa(self, to_send, key=None): """Send message with rsa encryption @@ -210,7 +336,7 @@ class ClientThread(threading.Thread): self.send(encrypted) return None - ############################################ COMMUNICATION WITHOUT CRYPTING ############################################ + ############################################ COMMUNICATION WITHOUT CRYPTING ######################################## def receive(self): """Receive message from connection @@ -253,6 +379,42 @@ class ClientThread(threading.Thread): self.client.send(END_MESSAGE) return None + def send_users(self): + print(self.server.clients.keys()) + self.send_aes(self.gen_header(type_=b"getUsersACK")+b"%!!%".join(list(self.server.clients.keys()))) + + def register_client(self): + """Register client + + :rtype: NoneType + :return: Nothing""" + self.server.register_client(self.rsa_client, self) + id_noeud, id_client = self.server.rsa_key.publickey().exportKey(), self.rsa_client + self.send_aes(self.gen_header(type_=b"registerACK") + id_noeud + b"{%=&%&=%}" + id_client) + + def send_to_me(self, to_send): + """Receive message from other poeple + + :param to_send: Message to send to client + :type to_send: bytes + + :rtype: NoneType + :return: Nothing""" + self.send(self.gen_header(type_=b"send", to_=self.rsa_client) + to_send) + return + + def send_to_other(self, id_dest, to_send): + """Send message to other client + + :param id_dest: id of receiver + :param to_send: Message to send + + :return: Nothing + :rtype: NoneType""" + server_response = self.server.send_to(id_dest, to_send) + self.send(self.gen_header(type_=b"sendACK"), server_response) + return + def run(self): # main de la connection du client """Run thread mainloop @@ -261,14 +423,25 @@ class ClientThread(threading.Thread): info(self.ip + "connected, initialize connection...") self.initialize() info(self.ip + "connection initialized.") + while self.running: + data = self.receive_aes() + header = self.extract_header(data) + print(header) + print(data) + print(self.rsa_client) + if header[b"type"] == b"register_client": + self.register_client() + elif header[b"type"] == b"getUsers": + self.send_users() self.client.close() if __name__ == "__main__": clients = [] + server = ServerThread(main_socket, ip=HOST, port=PORT) while True: main_socket.listen(1) # Waiting for incoming connections client_socket, (ip, PORT) = main_socket.accept() - newClient = ClientThread(client_socket, ip, PORT) + newClient = ClientThread(client_socket, ip, PORT, server) newClient.start() clients.append(newClient) diff --git a/server/private.pem b/server/private.pem new file mode 100644 index 0000000..5433c26 --- /dev/null +++ b/server/private.pem @@ -0,0 +1,57 @@ +-----BEGIN RSA PRIVATE KEY----- +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 +-----END RSA PRIVATE KEY----- \ No newline at end of file diff --git a/server/public.pem b/server/public.pem new file mode 100644 index 0000000..2bc1244 --- /dev/null +++ b/server/public.pem @@ -0,0 +1,15 @@ +-----BEGIN PUBLIC KEY----- +MIICYjANBgkqhkiG9w0BAQEFAAOCAk8AMIICSgKCAkEAlmEl3vGDG4qxqPvO98zC +pDbrFrNeTbwThiqCnuu0Cp5h/ejNeSChnRkmyOffMtvmBCmCJNw0vR9/Cpatzx9T +XekXUWRjXbUfR1ECQ2Fo0xqS3GE58F8HYnhra9+i3xJXSJRpk7P1FaKGakie0GGo +MCcImGZyWuSjNbUa4hj+I+Nlgf3rwQfll/06Wy7YLWXCXnNCTnirVYJooPphy3Qq +tNj+clwCvoY8F7Tz5PDfffiDPjxb+uOWwtfi0LecL5YqZC8aed/70WcujItkGQ2Y +hReYV+jsXvj1DTA0VB/RdrzRYeTNqYSoS7t8+cmWM27syEPb+11JLQZB4kPUB4yY +Ffk/a1ffkmEZYtqRdbndM20Loksr3C/jHRrmqfCjRVmL2wHK64wUUbGLKcSMLHkA +UR1HaeZ+PJ2qXX7ed4MBDRQDaMM7JGrkwz3hyBq2fblUT+OarHnlwRDvLL+XlACr +NJ7yvnigwCkx7MVwakhr0yWc0o9QHEmA2DnibE4JCrNfyAwV+hKs9p+F0XjbbutO +USXFxKdImKzf4NG1eNtMKFeIKZgtzm/JVhvlSC4p6ko+szBd89A11K1oHKRVNC64 +rnNH89o2qdT495HRfnFoEHgxA0nQH85QlCajOT0R122ha5ksJxXgj+HzTXiKa4Lt +TXy5kWWkYGMGxK6Xmxn32QPZHCgZA1L99uvZjr1hgkqxrI8p1wBPABN3vdr1CLwq +4kp0g+BOsFAb7X9rWn6xW9wTY8QmFW9Ze+K3Fn7aYg41AgMBAAE= +-----END PUBLIC KEY----- \ No newline at end of file