Il ne manque plus que à envoyer des messages
This commit is contained in:
parent
3f1940df00
commit
93aace85cb
30
RFC8497.md
30
RFC8497.md
@ -141,7 +141,7 @@ Communication entre un client et un noeud
|
|||||||
###### En-tête ######
|
###### En-tête ######
|
||||||
|
|
||||||
EICP2P2 V1
|
EICP2P2 V1
|
||||||
type: register
|
type: register_client
|
||||||
|
|
||||||
###### Contenu ######
|
###### Contenu ######
|
||||||
|
|
||||||
@ -160,11 +160,11 @@ Cette requête est envoyée par un client pour s'enregistrer sur le réseau. Le
|
|||||||
|
|
||||||
###### Contenu ######
|
###### Contenu ######
|
||||||
|
|
||||||
id_noeud::id_client
|
id_noeud{%=&%&=%}id_client
|
||||||
|
|
||||||
###### Utilisation ######
|
###### 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 ###
|
### Send ###
|
||||||
|
|
||||||
@ -191,7 +191,7 @@ Cette requête est envoyé par un client enregistré à un noeud pour envoyer un
|
|||||||
|
|
||||||
###### Contenu ######
|
###### Contenu ######
|
||||||
|
|
||||||
Rien
|
Rien/Erreur client incunnu
|
||||||
|
|
||||||
###### Utilisation ######
|
###### 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.
|
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 ###
|
### Ping ###
|
||||||
|
|
||||||
###### En-tête ######
|
###### En-tête ######
|
||||||
|
136
client/main.py
136
client/main.py
@ -18,10 +18,41 @@ try:
|
|||||||
except ModuleNotFoundError: # Pycryptodomex
|
except ModuleNotFoundError: # Pycryptodomex
|
||||||
from Cryptodome.PublicKey import RSA as RSA
|
from Cryptodome.PublicKey import RSA as RSA
|
||||||
from Cryptodome.Cipher import PKCS1_OAEP as PKCS1_OAEP
|
from Cryptodome.Cipher import PKCS1_OAEP as PKCS1_OAEP
|
||||||
|
from Cryptodome.Cipher import AES as AES
|
||||||
|
|
||||||
pycryptodome = True
|
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'):
|
def setup_logging(default_path='log_config.json', default_level=logging.INFO, env_key='LOG_CFG'):
|
||||||
"""Setup logging configuration
|
"""Setup logging configuration
|
||||||
"""
|
"""
|
||||||
@ -58,8 +89,8 @@ NAME = b"client1"
|
|||||||
VERSION = b"EICP2P2 V1"
|
VERSION = b"EICP2P2 V1"
|
||||||
|
|
||||||
REQUEST_TYPE = [
|
REQUEST_TYPE = [
|
||||||
b'ping', b'pingACK', b'updateAsk', b'updateBack', b'transfer', b'register', b'registerACK', b'send', b'sendACK',
|
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'exit', b'RSASend', b'init', b'getUsers', b'getUsersACK',
|
||||||
]
|
]
|
||||||
|
|
||||||
clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
@ -77,20 +108,38 @@ class MainThread(threading.Thread):
|
|||||||
self.rsa = None
|
self.rsa = None
|
||||||
self.aes_key = None
|
self.aes_key = None
|
||||||
self.clientSocket = None
|
self.clientSocket = None
|
||||||
|
self.users = {}
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
rsa = self.RsaGenThread(self)
|
rsa = RsaGenThread(self)
|
||||||
rsa.start()
|
rsa.start()
|
||||||
rsa.join()
|
rsa.join()
|
||||||
self.clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
self.clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
self.clientSocket.connect((HOST, PORT))
|
self.clientSocket.connect((HOST, PORT))
|
||||||
self.initialisation()
|
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):
|
def initialisation(self):
|
||||||
header = self.gen_header(b"RSASend", from_=b"client")
|
header = self.gen_header(b"RSASend", from_=b"client")
|
||||||
content = self.rsa.publickey().exportKey()
|
content = self.rsa.publickey().exportKey()
|
||||||
self.send(header + content)
|
self.send(header + content)
|
||||||
|
print("oki1")
|
||||||
data = self.receive_rsa()
|
data = self.receive_rsa()
|
||||||
|
print("oki2")
|
||||||
header = self.extract_header(data[:BUFFER_SIZE])
|
header = self.extract_header(data[:BUFFER_SIZE])
|
||||||
if header[b"type"] != b"init":
|
if header[b"type"] != b"init":
|
||||||
debug("Incorrect request type, end of connection")
|
debug("Incorrect request type, end of connection")
|
||||||
@ -139,34 +188,60 @@ class MainThread(threading.Thread):
|
|||||||
header += b"\nfrom: " + from_
|
header += b"\nfrom: " + from_
|
||||||
return header.ljust(BUFFER_SIZE, b';')
|
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):
|
def send_aes(self, to_send, key=None):
|
||||||
threading.Thread.__init__(self)
|
"""Send message with aes encryption
|
||||||
self.client = client_
|
|
||||||
self.difficulty = difficulty
|
|
||||||
|
|
||||||
def run(self):
|
:param to_send: Message to send
|
||||||
if os.path.isfile("private.pem"):
|
:type to_send: bytes
|
||||||
try:
|
:param key: key to replace self.aes_key
|
||||||
with open("private.pem", "rb") as keyfile:
|
:type key: bytes
|
||||||
rsa = RSA.importKey(keyfile.read())
|
|
||||||
if not rsa.has_private():
|
:rtype: NoneType
|
||||||
warning("Le fichier clef ne contient pas de clef privée")
|
:return: Nothing"""
|
||||||
raise ValueError
|
debug(b"Send with AES encryption: " + to_send)
|
||||||
self.client.rsa = rsa
|
if key is None:
|
||||||
except (IndexError, ValueError):
|
key = self.aes_key
|
||||||
warning("Fichier clef corrompu")
|
if key is None:
|
||||||
debug("Suppression du fichier clef corromu")
|
info("AES key not generated, connection failure.")
|
||||||
os.remove("private.pem")
|
self.client.send(b"Error")
|
||||||
if not os.path.isfile("private.pem"): # We're not using if/else because we may delete the file in the
|
return
|
||||||
# previous if statement
|
# Get RSA key
|
||||||
debug("Génération de la clef RSA pour %s" % self.client.name)
|
aes_object = AES.new(key, AES.MODE_ECB)
|
||||||
self.client.rsa = RSA.generate(BUFFER_SIZE + 256 * self.difficulty)
|
encrypted = b""
|
||||||
with open("private.pem", "wb") as keyfile:
|
for to_send_text in [to_send[i:i + 32] for i in range(0, len(to_send), 32)]:
|
||||||
keyfile.write(self.client.rsa.exportKey())
|
encrypted += aes_object.encrypt(to_send_text.ljust(32, b"\x00"))
|
||||||
with open("public.pem", "wb") as keyfile:
|
self.send(encrypted)
|
||||||
keyfile.write(self.client.rsa.publickey().exportKey())
|
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 ############################################
|
################################################ COMMUNICATION WITH RSA ############################################
|
||||||
|
|
||||||
@ -180,7 +255,8 @@ class MainThread(threading.Thread):
|
|||||||
cipher_rsa = PKCS1_OAEP.new(recipient_key)
|
cipher_rsa = PKCS1_OAEP.new(recipient_key)
|
||||||
raw = self.receive()
|
raw = self.receive()
|
||||||
content = b""
|
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)
|
content += cipher_rsa.decrypt(to_decrypt)
|
||||||
return content
|
return content
|
||||||
|
|
||||||
|
193
server/main.py
193
server/main.py
@ -13,6 +13,7 @@ try:
|
|||||||
from Crypto.PublicKey import RSA as RSA
|
from Crypto.PublicKey import RSA as RSA
|
||||||
# noinspection PyUnresolvedReferences
|
# noinspection PyUnresolvedReferences
|
||||||
from Crypto.Cipher import PKCS1_OAEP as PKCS1_OAEP
|
from Crypto.Cipher import PKCS1_OAEP as PKCS1_OAEP
|
||||||
|
from Crypto.Cipher import AES as AES
|
||||||
# noinspection PyUnresolvedReferences,PyProtectedMember
|
# noinspection PyUnresolvedReferences,PyProtectedMember
|
||||||
from Crypto.Random._UserFriendlyRNG import get_random_bytes as get_random_bytes
|
from Crypto.Random._UserFriendlyRNG import get_random_bytes as get_random_bytes
|
||||||
|
|
||||||
@ -20,6 +21,7 @@ try:
|
|||||||
except ModuleNotFoundError: # Pycryptodomex
|
except ModuleNotFoundError: # Pycryptodomex
|
||||||
from Cryptodome.PublicKey import RSA as RSA
|
from Cryptodome.PublicKey import RSA as RSA
|
||||||
from Cryptodome.Cipher import PKCS1_OAEP as PKCS1_OAEP
|
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
|
from Cryptodome.Random import get_random_bytes as get_random_bytes
|
||||||
|
|
||||||
pycryptodome = True
|
pycryptodome = True
|
||||||
@ -61,8 +63,8 @@ END_MESSAGE = bytes("fin".ljust(BUFFER_SIZE, ";"), "ascii")
|
|||||||
VERSION = b"EICP2P2 V1"
|
VERSION = b"EICP2P2 V1"
|
||||||
|
|
||||||
REQUEST_TYPE = [
|
REQUEST_TYPE = [
|
||||||
b'ping', b'pingACK', b'updateAsk', b'updateBack', b'transfer', b'register', b'registerACK', b'send', b'sendACK',
|
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'exit', b'RSASend', b'init', b'getUsers', b'getUsersACK',
|
||||||
]
|
]
|
||||||
|
|
||||||
DONE = 0
|
DONE = 0
|
||||||
@ -77,22 +79,99 @@ main_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|||||||
main_socket.bind((HOST, PORT))
|
main_socket.bind((HOST, PORT))
|
||||||
|
|
||||||
|
|
||||||
class ServerThread(threading.Thread):
|
|
||||||
"""Main server thread"""
|
|
||||||
|
|
||||||
#### Threads ####
|
#### 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):
|
class ClientThread(threading.Thread):
|
||||||
"""Main thread, for each client"""
|
"""Main thread, for each client"""
|
||||||
|
|
||||||
def __init__(self, clientsocket, ip_client, port):
|
def __init__(self, clientsocket, ip_client, port, server):
|
||||||
"""Create ClientThread object
|
"""Create ClientThread object
|
||||||
|
|
||||||
:param clientsocket: Client's socket
|
:param clientsocket: Client's socket
|
||||||
:param ip_client: Client's ip address
|
:param ip_client: Client's ip address
|
||||||
:param port: Client's connection PORT
|
:param port: Client's connection PORT
|
||||||
|
:param server: Server thread
|
||||||
:type clientsocket: socket.socket
|
:type clientsocket: socket.socket
|
||||||
:type ip_client: str
|
:type ip_client: str
|
||||||
:type port: int
|
:type port: int
|
||||||
|
:type server: ServerThread
|
||||||
|
|
||||||
:return: Nothing
|
:return: Nothing
|
||||||
:rtype: NoneType"""
|
:rtype: NoneType"""
|
||||||
@ -104,8 +183,9 @@ class ClientThread(threading.Thread):
|
|||||||
self.running = True
|
self.running = True
|
||||||
self.status = None
|
self.status = None
|
||||||
self.rsa_client = None
|
self.rsa_client = None
|
||||||
self.aes_key = get_random_bytes(64)
|
self.aes_key = get_random_bytes(32)
|
||||||
self.type = T_NONE
|
self.type = T_NONE
|
||||||
|
self.server = server
|
||||||
debug("Creation du thread pour %s reussie" % ip_client)
|
debug("Creation du thread pour %s reussie" % ip_client)
|
||||||
|
|
||||||
def initialize(self):
|
def initialize(self):
|
||||||
@ -181,7 +261,53 @@ class ClientThread(threading.Thread):
|
|||||||
header += b"\nfrom: " + from_,
|
header += b"\nfrom: " + from_,
|
||||||
return header.ljust(BUFFER_SIZE, b';')
|
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):
|
def send_rsa(self, to_send, key=None):
|
||||||
"""Send message with rsa encryption
|
"""Send message with rsa encryption
|
||||||
@ -210,7 +336,7 @@ class ClientThread(threading.Thread):
|
|||||||
self.send(encrypted)
|
self.send(encrypted)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
############################################ COMMUNICATION WITHOUT CRYPTING ############################################
|
############################################ COMMUNICATION WITHOUT CRYPTING ########################################
|
||||||
|
|
||||||
def receive(self):
|
def receive(self):
|
||||||
"""Receive message from connection
|
"""Receive message from connection
|
||||||
@ -253,6 +379,42 @@ class ClientThread(threading.Thread):
|
|||||||
self.client.send(END_MESSAGE)
|
self.client.send(END_MESSAGE)
|
||||||
return None
|
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
|
def run(self): # main de la connection du client
|
||||||
"""Run thread mainloop
|
"""Run thread mainloop
|
||||||
|
|
||||||
@ -261,14 +423,25 @@ class ClientThread(threading.Thread):
|
|||||||
info(self.ip + "connected, initialize connection...")
|
info(self.ip + "connected, initialize connection...")
|
||||||
self.initialize()
|
self.initialize()
|
||||||
info(self.ip + "connection initialized.")
|
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()
|
self.client.close()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
clients = []
|
clients = []
|
||||||
|
server = ServerThread(main_socket, ip=HOST, port=PORT)
|
||||||
while True:
|
while True:
|
||||||
main_socket.listen(1) # Waiting for incoming connections
|
main_socket.listen(1) # Waiting for incoming connections
|
||||||
client_socket, (ip, PORT) = main_socket.accept()
|
client_socket, (ip, PORT) = main_socket.accept()
|
||||||
newClient = ClientThread(client_socket, ip, PORT)
|
newClient = ClientThread(client_socket, ip, PORT, server)
|
||||||
newClient.start()
|
newClient.start()
|
||||||
clients.append(newClient)
|
clients.append(newClient)
|
||||||
|
57
server/private.pem
Normal file
57
server/private.pem
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
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
|
||||||
|
-----END RSA PRIVATE KEY-----
|
15
server/public.pem
Normal file
15
server/public.pem
Normal file
@ -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-----
|
Loading…
Reference in New Issue
Block a user