Compare commits
2 Commits
Author | SHA1 | Date | |
---|---|---|---|
3e11fec257 | |||
5d6519c57a |
12
.gitignore
vendored
12
.gitignore
vendored
@ -105,3 +105,15 @@ venv.bak/
|
|||||||
|
|
||||||
# pycharm
|
# pycharm
|
||||||
.idea/
|
.idea/
|
||||||
|
|
||||||
|
# Pipenv.lock
|
||||||
|
Pipfile.lock
|
||||||
|
|
||||||
|
# Dolphin
|
||||||
|
*.directory
|
||||||
|
|
||||||
|
# Private keys
|
||||||
|
*.pem
|
||||||
|
|
||||||
|
# Kate
|
||||||
|
*.kate-swp
|
||||||
|
12
Pipfile
12
Pipfile
@ -1,12 +1,12 @@
|
|||||||
[[source]]
|
[[source]]
|
||||||
url = "https://pypi.org/simple"
|
|
||||||
verify_ssl = true
|
|
||||||
name = "pypi"
|
name = "pypi"
|
||||||
|
verify_ssl = true
|
||||||
|
url = "https://pypi.org/simple"
|
||||||
|
|
||||||
[packages]
|
[packages]
|
||||||
pycryptodomex = "*"
|
pycrypto = "*"
|
||||||
|
|
||||||
[dev-packages]
|
|
||||||
|
|
||||||
[requires]
|
[requires]
|
||||||
python_version = "3.7"
|
python_version = "3.5"
|
||||||
|
|
||||||
|
[dev-packages]
|
||||||
|
55
Pipfile.lock
generated
55
Pipfile.lock
generated
@ -1,55 +0,0 @@
|
|||||||
{
|
|
||||||
"_meta": {
|
|
||||||
"hash": {
|
|
||||||
"sha256": "ea1158d96215416c8146e8deedecea8da28400d9f80633238e5816576965f13e"
|
|
||||||
},
|
|
||||||
"pipfile-spec": 6,
|
|
||||||
"requires": {
|
|
||||||
"python_version": "3.7"
|
|
||||||
},
|
|
||||||
"sources": [
|
|
||||||
{
|
|
||||||
"name": "pypi",
|
|
||||||
"url": "https://pypi.org/simple",
|
|
||||||
"verify_ssl": true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"default": {
|
|
||||||
"pycryptodomex": {
|
|
||||||
"hashes": [
|
|
||||||
"sha256:02c358fa2445821d110857266e4e400f110054694636efe678dc60ba22a1aaef",
|
|
||||||
"sha256:09989c8a1b83e576d02ad77b9b019648648c569febca41f58fa04b9d9fdd1e8f",
|
|
||||||
"sha256:0f8fe28aec591d1b86af596c9fc5f75fc0204fb1026188a44e5e1b199780f1e5",
|
|
||||||
"sha256:0fb58c2065030a5381f3c466aaa7c4de707901badad0d6a0575952bb10e6c35f",
|
|
||||||
"sha256:0fb9f3e6b28a280436afe9192a9957c7f56e20ceecb73f2d7db807368fdf3aaf",
|
|
||||||
"sha256:12ff38a68bbd743407018f9dd87d4cc21f9cb28fe2d8ba93beca004ada9a09ff",
|
|
||||||
"sha256:1650143106383bae79cbbda3701fd9979d0a624dba2ec2fa63f88cae29dd7174",
|
|
||||||
"sha256:20a646cd0e690b07b7da619bc5b3ee1467243b2e32dfff579825c3ad5d7637ab",
|
|
||||||
"sha256:284779f0908682657adb8c60d8484174baa0d2620fb1df49183be6e2e06e73ce",
|
|
||||||
"sha256:2f3ce5bfe81d975c45e4a3cbe2bef15b809acc24f952f5f6aa67c2ae3c1a6808",
|
|
||||||
"sha256:30ac12f0c9ac8332cc76832fea88a547b49ef60c31f74697ee2584f215723d4f",
|
|
||||||
"sha256:4f038b815d66dea0b1d4286515d96474204e137eb5d883229616781865902789",
|
|
||||||
"sha256:57199a867b9991b1950f438b788e818338cee8ed8698e2eebdc5664521ad92a9",
|
|
||||||
"sha256:5c5349385e9863e3bba6804899f4125c8335f66d090e892d6a5bb915f5c89d4c",
|
|
||||||
"sha256:5d546fac597b5007d5ff38c50c9031945057a6a6fa1ab7585058165d370ea202",
|
|
||||||
"sha256:614eddfa0cf325e49b5b803fcb41c9334de79c4b18bf8de07e7737e1efc1d2b9",
|
|
||||||
"sha256:82ae66244824d50b2b657c32e5912fde70a6e36f41e61f2869151f226204430d",
|
|
||||||
"sha256:96a733f3be325fb17c2ba79648e85ab446767af3dc3b396f1404b9397aa28fe5",
|
|
||||||
"sha256:9c3834d27c1cff84e2a5c218e373d80ebbb3edca81912656f16137f7f97e58e0",
|
|
||||||
"sha256:9f11823636128acbe4e17c35ff668f4d0a9f3133450753a0675525b6413aa1b0",
|
|
||||||
"sha256:a3f9ad4e3f90f14707776f13b886fbac491ebe65d96a64f3ce0b378e167c3bbf",
|
|
||||||
"sha256:a89dee72a0f5024cc1cbaf85535eee8d14e891384513145d2f368b5c481dcd54",
|
|
||||||
"sha256:ccadde651e712093052286ad9ee27f5aa5f657ca688a1bf6d5c41ade709467f3",
|
|
||||||
"sha256:ced9ea10977dd52cb1b936a92119fc38fcdc5eaa4148f925ef22bbf0f0d4a5bd",
|
|
||||||
"sha256:eb0c6d3b91d55e3481158ecf77f3963c1725454fdcf5b79302c27c1c9c0d2c2a",
|
|
||||||
"sha256:f6714569a4039287972c672a8bd4b8d7dc78a601def8b31ffa39cd2fec00cb4b",
|
|
||||||
"sha256:fa4036582c8755259d4b8f4fe203ae534b7b187dcea143ab53a24e0f3931d547",
|
|
||||||
"sha256:fb31bb0c8301e5a43d8d7aad22acabef65f28f7ab057eaeb2c21433309cc41e8"
|
|
||||||
],
|
|
||||||
"index": "pypi",
|
|
||||||
"version": "==3.7.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"develop": {}
|
|
||||||
}
|
|
46
RFC8497.md
46
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_client
|
type: register
|
||||||
|
|
||||||
###### 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_client`. Le noeud communique au client son id et l'id du noeud auquel il est connecté.
|
Réponse à un `register`. 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/Erreur client incunnu
|
Rien
|
||||||
|
|
||||||
###### Utilisation ######
|
###### Utilisation ######
|
||||||
|
|
||||||
@ -217,28 +217,6 @@ 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 ######
|
||||||
@ -272,15 +250,14 @@ Réponse du client à une requête de ping.
|
|||||||
Initialisation des connections
|
Initialisation des connections
|
||||||
------------------------------
|
------------------------------
|
||||||
|
|
||||||
### RSASend ###
|
### RSAGet ###
|
||||||
|
|
||||||
> En clair
|
> En clair
|
||||||
|
|
||||||
###### En-tête ######
|
###### En-tête ######
|
||||||
|
|
||||||
EICP2P2 V1
|
EICP2P2 V1
|
||||||
type: RSASend
|
type: RSAget
|
||||||
from: noeud/client
|
|
||||||
|
|
||||||
###### Contenu ######
|
###### Contenu ######
|
||||||
|
|
||||||
@ -293,12 +270,13 @@ Cette requête est utilisé pour initialiser la communication crypté entre deux
|
|||||||
|
|
||||||
### Init ###
|
### Init ###
|
||||||
|
|
||||||
> Chiffré avec la clef RSA publique recue avec la requete RSASend
|
> Chiffré avec la clef RSA publique recue avec la requete RSAGet
|
||||||
|
|
||||||
###### En-tête ######
|
###### En-tête ######
|
||||||
|
|
||||||
EICP2P2 V1
|
EICP2P2 V1
|
||||||
type: init
|
type: init
|
||||||
|
from: noeud/client
|
||||||
|
|
||||||
###### Contenu ######
|
###### Contenu ######
|
||||||
|
|
||||||
@ -306,13 +284,7 @@ Cette requête est utilisé pour initialiser la communication crypté entre deux
|
|||||||
|
|
||||||
###### Utilisation ######
|
###### Utilisation ######
|
||||||
|
|
||||||
Requête envoyée en réponse à RSASend pour initialiser la connection cryptée en AES.
|
Requête envoyée en réponse à RSAGet pour initialiser la connection cryptée en AES.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Error ###
|
|
||||||
|
|
||||||
Error
|
|
||||||
|
|
||||||
Tables
|
Tables
|
||||||
------
|
------
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
"server": {
|
"server": {
|
||||||
"level": "DEBUG",
|
"level": "DEBUG",
|
||||||
"handlers": [
|
"handlers": [
|
||||||
|
"console",
|
||||||
"info_file_handler",
|
"info_file_handler",
|
||||||
"error_file_handler"
|
"error_file_handler"
|
||||||
]
|
]
|
||||||
|
302
client/main.py
Normal file → Executable file
302
client/main.py
Normal file → Executable file
@ -6,51 +6,30 @@ import logging
|
|||||||
import logging.config
|
import logging.config
|
||||||
import os
|
import os
|
||||||
import socket
|
import socket
|
||||||
|
|
||||||
|
|
||||||
|
#### logging ####
|
||||||
|
# json decoder for int keys
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
|
|
||||||
|
class Decoder(json.JSONDecoder):
|
||||||
|
def decode(self, s, **kwargs):
|
||||||
|
result = super().decode(s) # result = super(Decoder, self).decode(s) for Python 2.x
|
||||||
|
return self._decode(result)
|
||||||
|
|
||||||
|
def _decode(self, o):
|
||||||
|
if isinstance(o, str):
|
||||||
try:
|
try:
|
||||||
# noinspection PyUnresolvedReferences
|
return int(o)
|
||||||
from Crypto.PublicKey import RSA as RSA
|
except ValueError:
|
||||||
# noinspection PyUnresolvedReferences
|
return o
|
||||||
from Crypto.Cipher import PKCS1_OAEP as PKCS1_OAEP
|
elif isinstance(o, dict):
|
||||||
|
return {k: self._decode(v) for k, v in o.items()}
|
||||||
pycryptodome = False
|
elif isinstance(o, list):
|
||||||
except ModuleNotFoundError: # Pycryptodomex
|
return [self._decode(v) for v in o]
|
||||||
from Cryptodome.PublicKey import RSA as RSA
|
else:
|
||||||
from Cryptodome.Cipher import PKCS1_OAEP as PKCS1_OAEP
|
return o
|
||||||
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'):
|
def setup_logging(default_path='log_config.json', default_level=logging.INFO, env_key='LOG_CFG'):
|
||||||
@ -81,238 +60,25 @@ critical = log_server.critical
|
|||||||
#### Variables ####
|
#### Variables ####
|
||||||
HOST = '127.0.0.1'
|
HOST = '127.0.0.1'
|
||||||
PORT = 8888
|
PORT = 8888
|
||||||
BUFFER_SIZE = 4096
|
BUFFER_SIZE = 16384
|
||||||
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_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)
|
clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
clientSocket.connect((HOST, PORT))
|
clientSocket.connect((HOST, PORT))
|
||||||
|
|
||||||
|
|
||||||
# ET ICI ON MET LE CLIENT
|
# ET ICI ON MET LE CLIENT
|
||||||
|
|
||||||
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
|
|
||||||
self.users = {
|
|
||||||
# id: rsa
|
|
||||||
}
|
|
||||||
self.connected_users = {
|
|
||||||
# id: (rsa, aes, nick)
|
|
||||||
}
|
|
||||||
|
|
||||||
def run(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")
|
|
||||||
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].rstrip(b";") 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
|
|
||||||
|
|
||||||
: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';')
|
|
||||||
|
|
||||||
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 = {i: contenu.split(b"%!!%")[i] for i in range(len(contenu.split(b"%!!%")))}
|
|
||||||
|
|
||||||
################################################ 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)
|
|
||||||
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 ############################################
|
|
||||||
|
|
||||||
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_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
|
|
||||||
|
|
||||||
############################################ 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
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
client = MainThread(NAME)
|
|
||||||
client.start()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,57 +0,0 @@
|
|||||||
-----BEGIN RSA PRIVATE KEY-----
|
|
||||||
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
|
|
||||||
-----END RSA PRIVATE KEY-----
|
|
@ -1,15 +0,0 @@
|
|||||||
-----BEGIN PUBLIC KEY-----
|
|
||||||
MIICYjANBgkqhkiG9w0BAQEFAAOCAk8AMIICSgKCAkEAyCjkX4LpaXrvh8oeVq6r
|
|
||||||
dNLNpVBUiJxSX8CJizqB6Z/m8/4ZR69V0H/MzVjngnczA9Z2ITsIJ3ZLpGxL5TNC
|
|
||||||
4Kv5q3LKsvhuSWMTq97q2bKaeCBrROOurG5FxWrTqLHbs5U47kJEDKH6Orn42l6t
|
|
||||||
jvl/74qWTRarpZ4lbNfIkbM45rp10OhZNnjCsuxlcWEhGn5bp6IrSsQ0ZIYfwNLw
|
|
||||||
sEDjkn/fCz9NY0ZouT8ua/RnEkW7s6KOAdoaQi6LSADq9BXK+c4Zdfb5E7ScBzHM
|
|
||||||
jl10AqyNSHZ3DnFL5AEdzC4ZbmXLSbAKuglFnplKoXRZm6rUb2rWU3NDQ9LVIoUp
|
|
||||||
OfHUD+ip6V9nuQHIS7KVHJ0hgu9s3lRwN5YwnNz5OqcxWB2eLw8PLaH0WNRTmfbl
|
|
||||||
9EEf2huhUpgXv/DI+7J0dfnSpxaGO0YAZnjm0x+E/ryXq3vpGb3uErgJ8iuro6MF
|
|
||||||
LE7u9iiAr8HQisGiVVIPgvmns3fqHJq1tJ1p0GSjHN+Of2QQPx7TSpt/5Ew3Y/pZ
|
|
||||||
/ho8vazIBe036v6NyENywrW+UWYWdB6m9boEcg6GElSA0kVMw37syuRw7O6FhiOw
|
|
||||||
JZNjAMA67siio1vJfHXrzLhFmlyUzE07raMFpG4aKw2zwo4PKLSxIiU66i9/ECbJ
|
|
||||||
+3yN7p+XXljCkni7KO9JSI64hETw7BiY+S/+ZqaipnB3hWxQFsZn36RfeU/BIfGz
|
|
||||||
kQ4+NdYZPgR4h64tcVv9BjZ8abqBb5id1wFRpKVDeDpDAgMBAAE=
|
|
||||||
-----END PUBLIC KEY-----
|
|
51
private.pem
51
private.pem
@ -1,51 +0,0 @@
|
|||||||
-----BEGIN RSA PRIVATE KEY-----
|
|
||||||
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
|
|
||||||
-----END RSA PRIVATE KEY-----
|
|
14
receiver.pem
14
receiver.pem
@ -1,14 +0,0 @@
|
|||||||
-----BEGIN PUBLIC KEY-----
|
|
||||||
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnyiVFNxPTuctHL12pPcB
|
|
||||||
zumJnSiA7CZtbUbgozPjuVuJJQcf8FPZEQWFphtUujZVMRi6PX3szkKhOb08pl75
|
|
||||||
yzoA9H1ql5UoutuGExc0PVzaTY5BtnU38q6XvyWTYz5TNaG2bhd9DuNv9JrMn+/y
|
|
||||||
dClxOGvTd4Y+7VI8RG8HHnwMrwRcLzQ2FSJD9mVSopFn+5Z0j0idog2O/SsZJM3c
|
|
||||||
8ieLoOHO9vxQO8xVaUIF74nVoNiLz/YrcAhU9N3y2KcjpAsQBbFznKeQ6AcW5WjC
|
|
||||||
9zZBVLElP2PAVd6EFKY9C6nuodsaICqgWZnyCh+tEI8i+IQq2RN1YySv+6Cn929w
|
|
||||||
VM2tDPxaYfziSLkW5Pk9oPJ43xHsjb8yFUKsoChPmo4Qe4AVkIIbxwVWG0wymWqE
|
|
||||||
uWeiKlc32badxf38dAm9TvgAApZ05cSIV6ieYP+ixjMFa2rrjkPtfcXey6O05D8u
|
|
||||||
TMQx9GPZRNezceRWI89Lip83raWqjhw+hUvbGaUL0B/z7XD1zskmQ9n+RnhYRVZr
|
|
||||||
YOTw2BWoGoMBC13/g7qG2RR+qrJFs1PLTbUgrzP5HkVpKzBvi2G3BxXGr0aflOtL
|
|
||||||
rOU275LjdkkJrOiNMdPrGsUe9S9XPK5irHampxnJOv5oOCQZ0m/bzKXJykZAJF9f
|
|
||||||
X8caOE++kTH0DSqsapE0fC8CAwEAAQ==
|
|
||||||
-----END PUBLIC KEY-----
|
|
@ -45,6 +45,7 @@
|
|||||||
"root": {
|
"root": {
|
||||||
"level": "INFO",
|
"level": "INFO",
|
||||||
"handlers": [
|
"handlers": [
|
||||||
|
"console",
|
||||||
"info_file_handler",
|
"info_file_handler",
|
||||||
"error_file_handler"
|
"error_file_handler"
|
||||||
]
|
]
|
||||||
|
409
server/main.py
Normal file → Executable file
409
server/main.py
Normal file → Executable file
@ -6,25 +6,30 @@ import logging
|
|||||||
import logging.config
|
import logging.config
|
||||||
import os
|
import os
|
||||||
import socket
|
import socket
|
||||||
|
|
||||||
|
|
||||||
|
#### logging ####
|
||||||
|
# json decoder for int keys
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
|
|
||||||
|
class Decoder(json.JSONDecoder):
|
||||||
|
def decode(self, s, **kwargs):
|
||||||
|
result = super().decode(s) # result = super(Decoder, self).decode(s) for Python 2.x
|
||||||
|
return self._decode(result)
|
||||||
|
|
||||||
|
def _decode(self, o):
|
||||||
|
if isinstance(o, str):
|
||||||
try:
|
try:
|
||||||
# noinspection PyUnresolvedReferences
|
return int(o)
|
||||||
from Crypto.PublicKey import RSA as RSA
|
except ValueError:
|
||||||
# noinspection PyUnresolvedReferences
|
return o
|
||||||
from Crypto.Cipher import PKCS1_OAEP as PKCS1_OAEP
|
elif isinstance(o, dict):
|
||||||
from Crypto.Cipher import AES as AES
|
return {k: self._decode(v) for k, v in o.items()}
|
||||||
# noinspection PyUnresolvedReferences,PyProtectedMember
|
elif isinstance(o, list):
|
||||||
from Crypto.Random._UserFriendlyRNG import get_random_bytes as get_random_bytes
|
return [self._decode(v) for v in o]
|
||||||
|
else:
|
||||||
pycryptodome = False
|
return o
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
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'):
|
||||||
@ -55,393 +60,49 @@ critical = log_server.critical
|
|||||||
#### Variables ####
|
#### Variables ####
|
||||||
HOST = ''
|
HOST = ''
|
||||||
PORT = 8888
|
PORT = 8888
|
||||||
BUFFER_SIZE = 4096
|
BUFFER_SIZE = 16384
|
||||||
CHUNK_SIZE = int(BUFFER_SIZE / 8)
|
|
||||||
BEGIN_MESSAGE = bytes("debut".ljust(BUFFER_SIZE, ";"), "ascii")
|
|
||||||
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_client', b'registerACK', b'send', b'sendACK',
|
|
||||||
b'exit', b'RSASend', b'init', b'getUsers', b'getUsersACK',
|
|
||||||
]
|
|
||||||
|
|
||||||
DONE = 0
|
|
||||||
ERROR = 1
|
|
||||||
|
|
||||||
T_NONE = 0b0000000000
|
|
||||||
T_NODE = 0b0000000001
|
|
||||||
T_CLIENT = 0b00000010
|
|
||||||
|
|
||||||
#### Socket ####
|
#### Socket ####
|
||||||
main_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
main_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
main_socket.bind((HOST, PORT))
|
main_socket.bind((HOST, PORT))
|
||||||
|
|
||||||
|
|
||||||
#### Threads ####
|
#### Threads ####
|
||||||
|
class clientThread(threading.Thread):
|
||||||
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"""
|
"""Main thread, for each client"""
|
||||||
|
|
||||||
def __init__(self, clientsocket, ip_client, port, server):
|
def __init__(self, clientsocket, ip, port):
|
||||||
"""Create ClientThread object
|
"""Create clientThread object
|
||||||
|
|
||||||
:param clientsocket: Client's socket
|
:param clentsocket: Client's socket
|
||||||
:param ip_client: Client's ip address
|
:param ip: 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: str
|
||||||
:type port: int
|
:type port: int
|
||||||
:type server: ServerThread
|
|
||||||
|
|
||||||
:return: Nothing
|
:return: Nothing
|
||||||
:rtype: NoneType"""
|
:rtype: NoneType"""
|
||||||
debug("Creation du thread pour %s" % ip_client)
|
debug("Creation du thread pour %s" % ip)
|
||||||
threading.Thread.__init__(self) # initialisation du thread
|
threading.Thread.__init__(self) # initialisation du thread
|
||||||
self.client = clientsocket
|
self.client = clientsocket
|
||||||
self.ip = ip_client
|
self.ip = ip
|
||||||
self.port = port
|
self.port = port
|
||||||
self.running = True
|
debug("Creation du thread pour %s reussie" % ip)
|
||||||
self.status = None
|
|
||||||
self.rsa_client = None
|
|
||||||
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):
|
|
||||||
"""Initialize connection with client
|
|
||||||
|
|
||||||
:rtype: NoneType
|
|
||||||
:return: Nothing"""
|
|
||||||
# Receive message
|
|
||||||
message = self.receive()
|
|
||||||
header = self.extract_header(message)
|
|
||||||
content = message[BUFFER_SIZE:]
|
|
||||||
if header.get(b"type", None) is None:
|
|
||||||
debug("The type field is not in the header")
|
|
||||||
self.send(b"Error")
|
|
||||||
return
|
|
||||||
if header.get(b"from", None) is None:
|
|
||||||
debug("The from field is not in the header")
|
|
||||||
self.send(b"error")
|
|
||||||
return
|
|
||||||
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
|
|
||||||
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].rstrip(b";") 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 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
|
|
||||||
|
|
||||||
:param to_send: Message to send
|
|
||||||
:type to_send: bytes
|
|
||||||
:param key: key to replace self.client_key
|
|
||||||
:type key: bytes
|
|
||||||
|
|
||||||
:rtype: NoneType
|
|
||||||
:return: Nothing"""
|
|
||||||
debug(b"Send with RSA encryption: " + to_send + bytes(str(self.ip), "ascii"))
|
|
||||||
if key is None:
|
|
||||||
key = self.rsa_client
|
|
||||||
if key is None:
|
|
||||||
info("RSA key not received, connection failure.")
|
|
||||||
self.client.send(b"Error")
|
|
||||||
return
|
|
||||||
# Get RSA key
|
|
||||||
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)]:
|
|
||||||
encrypted += cipher_rsa.encrypt(to_send_text)
|
|
||||||
self.send(encrypted)
|
|
||||||
return None
|
|
||||||
|
|
||||||
############################################ 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.client.recv(BUFFER_SIZE)
|
|
||||||
content = b''
|
|
||||||
while chunk != END_MESSAGE:
|
|
||||||
chunk = self.client.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 from" + bytes(str(self.ip), 'ascii') + b" : " + 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 + b" to " + bytes(str(self.ip), "ascii"))
|
|
||||||
# Sending the message start
|
|
||||||
self.client.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.client.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.client.send(END_MESSAGE)
|
|
||||||
return None
|
|
||||||
|
|
||||||
def send_users(self):
|
|
||||||
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
|
||||||
|
|
||||||
:return: Nothing
|
:return: Nothing
|
||||||
:rtype: NoneType"""
|
:rtype: NoneType"""
|
||||||
info(self.ip + "connected, initialize connection...")
|
### ICI ON MET LA BOUCLE PRINCIPALE DE 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()
|
|
||||||
elif
|
|
||||||
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) # ecoutes des connections entrantes
|
||||||
client_socket, (ip, PORT) = main_socket.accept()
|
clientsocket, (ip, PORT) = main_socket.accept()
|
||||||
newClient = ClientThread(client_socket, ip, PORT, server)
|
newClient = clientThread(clientsocket, ip, PORT)
|
||||||
newClient.start()
|
newClient.start()
|
||||||
clients.append(newClient)
|
clients.append(newClient)
|
||||||
|
@ -1,57 +0,0 @@
|
|||||||
-----BEGIN RSA PRIVATE KEY-----
|
|
||||||
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
|
|
||||||
-----END RSA PRIVATE KEY-----
|
|
@ -1,15 +0,0 @@
|
|||||||
-----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