Il ne manque plus que à envoyer des messages

This commit is contained in:
Fomys 2018-11-27 15:33:51 +01:00
parent 3f1940df00
commit 93aace85cb
5 changed files with 387 additions and 44 deletions

View File

@ -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 ######

View File

@ -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

View File

@ -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)

57
server/private.pem Normal file
View File

@ -0,0 +1,57 @@
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----

15
server/public.pem Normal file
View 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-----