diff --git a/RFC8497.md b/RFC8497.md index a9496ce..192e5ef 100644 --- a/RFC8497.md +++ b/RFC8497.md @@ -257,7 +257,8 @@ Initialisation des connections ###### En-tête ###### EICP2P2 V1 - type: RSAget + type: RSASend + from: noeud/client ###### Contenu ###### @@ -276,7 +277,6 @@ Cette requête est utilisé pour initialiser la communication crypté entre deux EICP2P2 V1 type: init - from: noeud/client ###### Contenu ###### diff --git a/client/main.py b/client/main.py index b1b28c9..9ff233d 100644 --- a/client/main.py +++ b/client/main.py @@ -6,16 +6,19 @@ import logging import logging.config import os import socket +import threading try: # noinspection PyUnresolvedReferences from Crypto.PublicKey import RSA as RSA # noinspection PyUnresolvedReferences from Crypto.Cipher import PKCS1_OAEP + pycryptodome = False except ModuleNotFoundError: # Pycryptodomex from Cryptodome.PublicKey import RSA as RSA from Cryptodome.Cipher import PKCS1_OAEP + pycryptodome = True @@ -49,6 +52,15 @@ HOST = '127.0.0.1' PORT = 8888 BUFFER_SIZE = 4096 CHUNK_SIZE = int(BUFFER_SIZE / 8) +BEGIN_MESSAGE = bytes("debut".ljust(BUFFER_SIZE, ";"), "ascii") +END_MESSAGE = bytes("fin".ljust(BUFFER_SIZE, ";"), "ascii") +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', +] clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) clientSocket.connect((HOST, PORT)) @@ -56,67 +68,169 @@ clientSocket.connect((HOST, PORT)) # ET ICI ON MET LE CLIENT -def send(to_send): - clientSocket.send(BEGIN_MESSAGE) - i = 0 - for to_send_text in [to_send[i:i + BUFFER_SIZE - 2] for i in range(0, len(to_send), BUFFER_SIZE - 2)]: - print((len(to_send_text)).to_bytes(2, byteorder='big')) - print((len(to_send_text)).to_bytes(2, byteorder='big') + to_send_text.ljust(BUFFER_SIZE, b";")) - clientSocket.send((len(to_send_text)).to_bytes(2, byteorder='big') + to_send_text.ljust(BUFFER_SIZE - 2, b";")) - i += 1 - print(i) - clientSocket.send(END_MESSAGE) +class MainThread(threading.Thread): + """Main client class, for each identity.""" + + def __init__(self, name): + threading.Thread.__init__(self) + self.name = name + self.rsa = None + self.aes_key = None + self.clientSocket = None + + def run(self): + rsa = self.RsaGenThread(self) + rsa.start() + rsa.join() + print(type(self.rsa)) + self.clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.clientSocket.connect((HOST, PORT)) + self.initialisation() + + def initialisation(self): + header = self.gen_header(b"RSASend", from_=b"client") + content = self.rsa.publickey().exportKey() + self.send(header + content) + data = self.receive_rsa() + header = self.extract_header(data[:BUFFER_SIZE]) + if header["type"] != b"init": + debug("Incorrect request type, end of connection") + return + self.aes_key = data[BUFFER_SIZE:] + debug("End of initialisation") + + @staticmethod + def extract_header(data): + """Extract header from data + + :param data: Data to extract header + :type data: bytes + + :return: Dictionary with header datas + :rtype: dict{bytes: bytes}""" + if len(data) > BUFFER_SIZE: + debug("Header too long") + data = data[:BUFFER_SIZE] + data_lines = data.split(b'\n') + if data_lines[0] != VERSION: + raise ValueError("Version is incorrect.") + return { + l.split(b": ")[0]: l.split(b": ")[1] for l in data_lines + } + + @staticmethod + def gen_header(type_, to_=None, from_=None): + """Generate header + + :param type_: Request type + :param to_: `to` field in header, cf ../RFC8497.md + :param from_: `from` field in header, cf ../RFC8497.md + :type type_: bytes + :type to_: bytes + :type from_: bytes + + :return: header + :rtype: bytes""" + if type_ not in REQUEST_TYPE: + raise ValueError("Unknown request type") + return + header = VERSION + b"\ntype: " + type_ + if to_: + header += b"\nto: " + to_ + if from_: + header += b"\nfrom: " + from_ + return header.ljust(BUFFER_SIZE, b';') + + class RsaGenThread(threading.Thread): + + def __init__(self, client_, difficulty=4): + 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()) + + ################################################ COMMUNICATION WITH RSA ############################################ + + def receive_rsa(self, rsa_key=None): + if rsa_key is None: + rsa_key = self.rsa.exportKey() + if rsa_key is None: + info("RSA key not generated, connection failure.") + return + recipient_key = RSA.importKey(rsa_key) + cipher_rsa = PKCS1_OAEP.new(recipient_key) + raw = self.receive() + content = b"" + for to_send_text in [raw[i:i + CHUNK_SIZE] for i in range(0, len(raw), CHUNK_SIZE)]: + print(content) + content += cipher_rsa.decrypt(to_send_text) + return content + + ############################################ COMMUNICATION WITHOUT CRYPTING ######################################## + + def receive(self): + """Receive message from connection + + :rtype: bytes + :return: Message's content""" + chunk = bytes("", "ascii") # Temp variable to store received datas + while chunk != BEGIN_MESSAGE: + chunk = self.clientSocket.recv(BUFFER_SIZE) + content = b'' + while chunk != END_MESSAGE: + chunk = self.clientSocket.recv(BUFFER_SIZE) + # Get only interesting chucks + if chunk != END_MESSAGE: + # Get content part + # int.from_bytes(chunk[:2], byteorder='big') == Get content size + content += chunk[2:int.from_bytes(chunk[:2], byteorder='big')+2] + debug(b"Received : " + content) + return content + + def send(self, to_send): + """Send message to connection + + :param to_send: message to send + :type to_send: bytes + + :return: Nothing + :rtype: NoneType""" + debug(b"Send " + to_send) + # Sending the message start + self.clientSocket.send(BEGIN_MESSAGE) + i = 0 + for to_send_text in [to_send[i:i + BUFFER_SIZE - 2] for i in range(0, len(to_send), BUFFER_SIZE - 2)]: + self.clientSocket.send( + (len(to_send_text)).to_bytes(2, byteorder='big') # Size of the message contained by the chunk + + to_send_text.ljust(BUFFER_SIZE - 2, bytes(1)) # Content of the chunk + ) + i += 1 + # Sending the message stop + self.clientSocket.send(END_MESSAGE) + return None -BEGIN_MESSAGE = bytes("debut", "ascii").ljust(BUFFER_SIZE, b";") -END_MESSAGE = bytes("fin", "ascii").ljust(BUFFER_SIZE, b";") -HEADER_TXT = """\ -EICP2P2 V1 -type: RSASend""" -HEADER = bytes(HEADER_TXT, "ascii").ljust(BUFFER_SIZE, b";") - -## création des clef RSA -RSA_KEY_SIZE = CHUNK_SIZE * 2 -key = RSA.generate(BUFFER_SIZE * 2) -private_key = key.export_key() -file_out = open("private.pem", "wb") -file_out.write(private_key) -public_key = key.publickey().export_key() -file_out = open("receiver.pem", "wb") -file_out.write(public_key) -to_send = public_key.ljust(BUFFER_SIZE, b';') - -clientSocket.send(BEGIN_MESSAGE) -clientSocket.send(HEADER) -clientSocket.send(to_send) -clientSocket.send(END_MESSAGE) - -print('ok') -chunk = bytes("", "ascii") -while chunk != BEGIN_MESSAGE: - chunk = clientSocket.recv(BUFFER_SIZE) -last_chunk = chunk -while last_chunk != END_MESSAGE: - last_chunk = clientSocket.recv(BUFFER_SIZE) - chunk += last_chunk - -print(len(chunk[BUFFER_SIZE:-BUFFER_SIZE])) -chunk = chunk[BUFFER_SIZE:-BUFFER_SIZE] - -# HEADER+AES key are encypted in same time, so decrypt time at same time -cipher_rsa = PKCS1_OAEP.new(key) -texte_to_decrypt = b'' - -for ligne in [chunk[i:i + BUFFER_SIZE] for i in range(0, len(chunk), BUFFER_SIZE)]: - to_decrypt = ligne[2:] - to_decrypt = to_decrypt[:int.from_bytes(ligne[:2], byteorder='big')] - texte_to_decrypt += to_decrypt -print(len(texte_to_decrypt)) -texte = b'' -for to_decrypt in [texte_to_decrypt[i:i + RSA_KEY_SIZE] for i in range(0, len(texte_to_decrypt), RSA_KEY_SIZE)]: - print(len(to_decrypt)) - print(to_decrypt) - print(texte) - print(len(texte)) - texte += cipher_rsa.decrypt(to_decrypt) -print(texte) +if __name__ == "__main__": + client = MainThread(NAME) + client.start() diff --git a/client/private.pem b/client/private.pem index 8389410..00cb862 100644 --- a/client/private.pem +++ b/client/private.pem @@ -1,99 +1,63 @@ -----BEGIN RSA PRIVATE KEY----- -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 -----END RSA PRIVATE KEY----- \ No newline at end of file diff --git a/client/public.pem b/client/public.pem new file mode 100644 index 0000000..d745b49 --- /dev/null +++ b/client/public.pem @@ -0,0 +1,17 @@ +-----BEGIN PUBLIC KEY----- +MIICojANBgkqhkiG9w0BAQEFAAOCAo8AMIICigKCAoEAmoi9rbZ6kiCZMaLeX46S +KQ+hN8kkt/d6VV6pH7n8Mw9Di4xc2dvosVGwBVvsDzYC4sS5+orU76ps0uvELZgQ +Q8++2bfXXeRYWeucrZSA850vfokVKDTjkNVCJoOUGBeNgVxh2I8Mzn8logyFvbP6 +TQKRz+lY+ah7uKA2bp3PTr7uNrB4hhFvfwVBOMu9ismziBOy6Jjj4nHzhpWjPug7 +cWhiae2jPdacGCmqRog1cAspiyZ7Lkg+0pUrJWMeRHtCfhA8KHwYPQj423rO7Dz6 +lAEN/yqJeU34dva+rqWFPsrrXpO5FyJwa1VWqLZQvI3KjMmGd4d2Uxp4tIkJyEwE +v7IiKKc7xcl4hoesQr4dQiBVD7434zhzvk4N1BPwq7dY0ryYYyv0UhAw3oJyk3GE +agCejts0cej/MgugiR4qHkes59ZBd8KN96xI9J4iCSfFoOL8GqgsSYkD0rAn+JOY +advvdhD+p2lok0PqaOZm702MbUO+d0NEZa18z0YrEM2ttig327g0X7o8P/zwrh0i +5BCVtD6qeO2RFub0sDOYvqmDP2ueuX5lWq5oERi33Yxm7cEfZMD6i8eD03QIIWIU +4R4drs9VmPoqsSXPLxn0o1W7qo27rIUrfgFylmQdWPef/rsEP0RVfaLoDNL1e/Fg +RNi1eeueNlFoFgob/9GNekLhjQneTnvPntbFKD0fgYcmskW48J1eCego9CXKzfH+ +QMlDAknkq16ykmvyiNMisAGgxif9vnACkT4l3srHpv7PRDBR7YRS/4Yeu64FH9Oy +QkX4eE9MCY8GdNfYE4Q0GQzDtmCpfAWO0oXOoFLA0CZZD4pqTKB7XnmUpjd+Wbfs +mwIDAQAB +-----END PUBLIC KEY----- \ No newline at end of file diff --git a/client/receiver.pem b/client/receiver.pem deleted file mode 100644 index 4e51916..0000000 --- a/client/receiver.pem +++ /dev/null @@ -1,25 +0,0 @@ ------BEGIN PUBLIC KEY----- -MIIEIjANBgkqhkiG9w0BAQEFAAOCBA8AMIIECgKCBAEAj00qbP8CXp1dbqXG4vV+ -chzJx7HvkuTWqB3hQo712LjtseJ/i3KltwWHB+QAZ1GyswmJNW2KVDyyIq74d6K1 -bxy+EoSiXMctZdK3l5xL0JQwCnkaporyAuxwMkqu9scpcZ7rMIsphdvk6V4OmJdL -F/LLHLRsiMKGiaYmmzB5nyQDkiQ0+Pxmf+baMQ6YT713O9z2aunKdrMl8sQpbms+ -QUOmj6VLrJ9+ttcpRoTx0LxW0yl3bxKM7LrMnHazOEwLR2pnTlHB5NanmDyts1XU -6CzxFuCA8o3MLjpOIEw7IrllcDvFnZrh9SrtzKaCJIXhIT5yS4q/hZ7w9BWZBKzm -miudGmNYeyJUeVfnqk7AnofE4Rb95jnUWQkl3m8h1CkLRS7p0DVTvVqyeEPWXwgv -zGhLZP9xBDlQJMuNoRS8xqSy/7KWdunUt5oWPB/UwAsDLerSWp18Yi1g4q1d8o1S -2Q8t5kqOE6U985jyz9YPtCcFYQUDuyXWaFTTeGEfcY04pKt/rjffiEmJPSdSCmuC -IPx56qwzvSoUsWmf/sjquQaCvtIpftJhp3L0eoe4BBFPnAybyKeTz8ZBzchZb9h0 -gH1QxHhMA51kcaJDn8pojNDup5ZgMjrxAY9LBAhUS1hggAPf88eL23jEKYn8FYFl -Q/xuc2N/Hd31IK4U77NMGCGYIVPbDAmo9hNOWE8wEy50XNklmBIYPpWpWR1nobFH -Cbyu6Um1vBGYUVEzP7AVAFeUebQTuvWHk1OZosv8SYeUvcwl3rP+R0+eokjnR7Pz -XfrB1lBEN+jqBHrRX2Z9GDiJTpCRaxN2dP5zbT+24bhg24mCjelUzvNLUTyguDMJ -LkfScnOszFmM+d1rtWDLh/AjphoTfcCb3VWnLCcCJ4fklV0065vMotPlFxXBmFDD -DKQlam2tfue/SSJjpE27lcWnXz7tmH6O4GpOvd4/Og8PWwWRsx9xcRUZsY+6knRY -oZ77sHYRxoH/M9RqVf6dxA802gv97+lzLKzE0AeNm40XZnmxI7aUSzi2N93A4ykP -f6/HZbN0KqhdJ9PSMTawRZh/KvMx21El5W7l8GFLJMubfXHQ36dgNOEEFiekF9Do -X0l8i8Ev6RdhrHJtJLDVE391yxx1hgW/JzB5hmcc8ryhtx7HsBt5vtrxE0JM1/9P -xmOqqG9gXNY02ErkTK4TrJGkAx0z4ZGKh9BSypYtTxPWq5cDuT9q7gZTOnHZ+HtS -oWnGRKwwLlLmyo8ACcVXzCbj/ZfqVcWZkVDM2rlCF9O7xkeAQNJUKvuLMVm4Zlqz -M14TKzIOUtquanyx6zbajRNROE95Q8QAZw8I3P0pYY3+qX/7D0HJSGSN6cuNsngK -AQIDAQAB ------END PUBLIC KEY----- \ No newline at end of file diff --git a/server/main.py b/server/main.py index 83b714a..09f4143 100644 --- a/server/main.py +++ b/server/main.py @@ -58,11 +58,20 @@ CHUNK_SIZE = int(BUFFER_SIZE / 8) BEGIN_MESSAGE = bytes("debut".ljust(BUFFER_SIZE, ";"), "ascii") END_MESSAGE = bytes("fin".ljust(BUFFER_SIZE, ";"), "ascii") -VERSION = "EICP2P2 V1" +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', +] DONE = 0 ERROR = 1 +T_NONE = 0b0000000000 +T_NODE = 0b0000000001 +T_CLIENT = 0b00000010 + #### Socket #### main_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) main_socket.bind((HOST, PORT)) @@ -93,6 +102,7 @@ class ClientThread(threading.Thread): self.status = None self.rsa_client = None self.aes_key = get_random_bytes(64) + self.type = T_NONE debug("Creation du thread pour %s reussie" % ip_client) def initialize(self): @@ -102,37 +112,73 @@ class ClientThread(threading.Thread): :return: Nothing""" # Receive message message = self.receive() - # Get informations - header = message[:BUFFER_SIZE] + header = self.extract_header(message) content = message[BUFFER_SIZE:] - # Extract header data - header_txt = header.decode("ascii").rstrip(";") - version = header_txt.split("\n")[0] - # Extraction des champs du header - if version != VERSION: - debug("Incorrect protocol version.") - self.send(b"Error") - # Extract information from header - champs = {l.split(": ")[0]: l.split(": ")[1] for l in header_txt.split('\n')[1:]} - - if champs.get("type", None) is None: + if header.get(b"type", None) is None: debug("The type field is not in the header") self.send(b"Error") return - - if self.status is None and champs["type"] != "RSASend": - debug("Requête différente de RASSend avec une connection non initialisée") - self.send(b"Error".ljust(BUFFER_SIZE, b";")) + if header.get(b"from", None) is None: + debug("The from field is not in the header") + self.send(b"error") return - - if champs["type"] == "RSASend": + if self.status is None and header[b"type"] != b"RSASend": + debug("Requête différente de RSASend avec une connection non initialisée") + self.send(b"Error") + return + if header[b"type"] == b"RSASend": + self.type = T_CLIENT if header[b"from"] == b"client" else T_NODE debug("Réception de la clef RSA de %s", self.ip) - self.rsa_client = content.rstrip(b";").rstrip(b' ') - header = bytes((VERSION + "\ntype: init").ljust(BUFFER_SIZE, ";"), 'ascii') - content = self.aes_key.ljust(BUFFER_SIZE, b";") + print(content) + self.rsa_client = content + header = self.gen_header(b"init") + content = self.aes_key self.send_rsa(header + content) return + @staticmethod + def extract_header(data): + """Extract header from data + + :param data: Data to extract header + :type data: bytes + + :return: Dictionary with header datas + :rtype: dict{bytes: bytes}""" + if len(data) > BUFFER_SIZE: + debug("Header too long") + data = data[:BUFFER_SIZE] + data_lines = data.split(b'\n') + if data_lines[0] != VERSION: + raise ValueError("Version is incorrect.") + return { + l.split(b": ")[0]: l.split(b": ")[1] for l in data_lines[1:] + } + + @staticmethod + def gen_header(type_, to_=None, from_=None): + """Generate header + + :param type_: Request type + :param to_: `to` field in header, cf ../RFC8497.md + :param from_: `from` field in header, cf ../RFC8497.md + :type type_: bytes + :type to_: bytes + :type from_: bytes + + :raise ValueError: `type_` is not a valid request type + + :return: header + :rtype: bytes""" + if type_ not in REQUEST_TYPE: + raise ValueError("Unknown request type") + header = VERSION + b"\ntype: " + type_ + if to_: + header += b"\nto: " + to_ + if from_: + header += b"\nfrom: " + from_, + return header.ljust(BUFFER_SIZE, b';') + ################################################ COMMUNICATION WITH RSA ################################################ def send_rsa(self, to_send, key=None): @@ -150,18 +196,15 @@ class ClientThread(threading.Thread): key = self.rsa_client if key is None: info("RSA key not received, connection failure.") - self.client.send(b"Error".ljust(BUFFER_SIZE, bytes(1))) + self.client.send(b"Error") return # Get RSA key - print(len(to_send)) recipient_key = RSA.importKey(key) # RSA encryption object cipher_rsa = PKCS1_OAEP.new(recipient_key) encrypted = b"" for to_send_text in [to_send[i:i + CHUNK_SIZE] for i in range(0, len(to_send), CHUNK_SIZE)]: - print(len(to_send_text)) encrypted += cipher_rsa.encrypt(to_send_text) - print(len(encrypted)) self.send(encrypted) return None @@ -182,8 +225,10 @@ class ClientThread(threading.Thread): if chunk != END_MESSAGE: # Get content part # int.from_bytes(chunk[:2], byteorder='big') == Get content size - content += chunk[2:int.from_bytes(chunk[:2], byteorder='big')] - debug(b"Received from" + bytes(str(self.ip), ascii) + b" : " + content) + content += chunk[2:int.from_bytes(chunk[:2], byteorder='big')] #+2] # Avec le +2 il me mange plus les caractères mais je sais pas pourquoi @suwako + print(chunk[2:int.from_bytes(chunk[:2], byteorder='big')]) + print(content[:BUFFER_SIZE]) + debug(b"Received from" + bytes(str(self.ip), 'ascii') + b" : " + content) return content def send(self, to_send): @@ -198,7 +243,6 @@ class ClientThread(threading.Thread): # Sending the message start self.client.send(BEGIN_MESSAGE) i = 0 - print(len(to_send)) for to_send_text in [to_send[i:i + BUFFER_SIZE - 2] for i in range(0, len(to_send), BUFFER_SIZE - 2)]: self.client.send( (len(to_send_text)).to_bytes(2, byteorder='big') # Size of the message contained by the chunk @@ -217,7 +261,6 @@ class ClientThread(threading.Thread): info(self.ip + "connected, initialize connection...") self.initialize() info(self.ip + "connection initialized.") - print("done") self.client.close()