First try to crypt connection

This commit is contained in:
louis chauvet 2018-11-15 20:29:32 +01:00
parent fdb9d3eefb
commit 21679ebb92
9 changed files with 223 additions and 25 deletions

3
.gitignore vendored
View File

@ -105,6 +105,3 @@ venv.bak/
# pycharm
.idea/
# Pipenv.lock
Pipfile.lock

12
Pipfile
View File

@ -1,12 +1,12 @@
[[source]]
name = "pypi"
verify_ssl = true
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"
[packages]
pycrypto = "*"
[requires]
python_version = "3.5"
pycryptodome = "*"
[dev-packages]
[requires]
python_version = "3.7"

View File

@ -250,7 +250,7 @@ Réponse du client à une requête de ping.
Initialisation des connections
------------------------------
### RSAGet ###
### RSASend ###
> En clair
@ -270,7 +270,7 @@ Cette requête est utilisé pour initialiser la communication crypté entre deux
### Init ###
> Chiffré avec la clef RSA publique recue avec la requete RSAGet
> Chiffré avec la clef RSA publique recue avec la requete RSASend
###### En-tête ######
@ -284,7 +284,11 @@ Cette requête est utilisé pour initialiser la communication crypté entre deux
###### Utilisation ######
Requête envoyée en réponse à RSAGet pour initialiser la connection cryptée en AES.
Requête envoyée en réponse à RSASend pour initialiser la connection cryptée en AES.
### Error ###
Error
Tables
------

View File

@ -36,7 +36,6 @@
"server": {
"level": "DEBUG",
"handlers": [
"console",
"info_file_handler",
"error_file_handler"
]

View File

@ -12,6 +12,9 @@ import socket
# json decoder for int keys
import threading
from Crypto.Cipher import PKCS1_OAEP
from Crypto.PublicKey import RSA
class Decoder(json.JSONDecoder):
def decode(self, s, **kwargs):
@ -60,7 +63,7 @@ critical = log_server.critical
#### Variables ####
HOST = '127.0.0.1'
PORT = 8888
BUFFER_SIZE = 16384
BUFFER_SIZE = 4096
clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
clientSocket.connect((HOST, PORT))
@ -69,13 +72,50 @@ clientSocket.connect((HOST, PORT))
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
print(1024)
key = RSA.generate(BUFFER_SIZE)
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')
# BEGIN
chunk = clientSocket.recv(BUFFER_SIZE)
print(chunk)
# HEADER
cry_header = clientSocket.recv(BUFFER_SIZE).rstrip(b';')
print(cry_header)
# AESKEY
cry_aeskey = clientSocket.recv(BUFFER_SIZE).rstrip(b";")
print(cry_aeskey)
# END
chunk = clientSocket.recv(BUFFER_SIZE)
print(chunk)
# HEADER+AES key are encypted in same time, so decrypt thme at same time
cipher_rsa = PKCS1_OAEP.new(key)
t = cry_header+cry_aeskey
for to_decrypt in [t[i:i + int(len(public_key)/16)] for i in range(0, len(t), int(len(public_key)/16))]:
print(len(to_decrypt))
print(cipher_rsa.decrypt(to_decrypt))

51
client/private.pem Normal file
View File

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

14
client/receiver.pem Normal file
View File

@ -0,0 +1,14 @@
-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAvlMf7Wn+JRaFR4ErqgpQ
A3m86J++XPRZrKK6UJtdUqGI3XugiqbYUSr2n5+LOlfPNDQ6okcqGX+uJFaetWii
JLqzYvl+UjXwDK/jvCwlHvnjmViUw0MDzKyVfiNfwWAsoQXuQqk+vJWwyFuskxXI
QDRlHoye6KGsciweDcJjqqwurw5EbrozOeuC8pkl4gxK8xQcc6sYxc8Rs5EjYug5
qRbNw8FHiM6AIovYlrew2pzAyUDTPkOmmDZzESlmLWhTeS0GEaewvv+WX2yzE3yF
e9tSAO8SlBGaJ3LNpGIwDKgLH+9kFbQPkcLB0AnGnTAVvS/6nALWVYkXv98JacXV
GXBkWobn3IvWZ1djUXMpgs4haJfpCx5+KoRwkdBjQzPC/Ztx94lE9wd+3nNfusJV
IzZVcdfysbojbcNLnp77NYBFaAxw32U6m4jVYjAxr/NSw9VEcxiWshuv/UU3f9C1
rA3yagYOhLGCxtMiNtyXtujmmT2eVVoCePLveOWzeV+gLWm2ISU1RJ78vOhMc6T5
H9KJT4A50hI0LYa9fL141qOON3iwqzUT4dnMTfaXHXjTdybTku1es0GWkxorb2vl
I7AY9qPiuetrdW6EK5Xittc0gaeFSXwXoBAZStGk1rKy2HP1nMsfzv7MjMdqtPhI
CJ+LjgilL/ZhhfqNWwSWdIkCAwEAAQ==
-----END PUBLIC KEY-----

View File

@ -45,7 +45,6 @@
"root": {
"level": "INFO",
"handlers": [
"console",
"info_file_handler",
"error_file_handler"
]

View File

@ -6,11 +6,24 @@ import logging
import logging.config
import os
import socket
import threading
#### logging ####
# json decoder for int keys
import threading
from Crypto.Cipher import PKCS1_OAEP
from Crypto.PublicKey import RSA
from Crypto.Random import get_random_bytes
def make_hashable(o):
if isinstance(o, (tuple, list)):
return tuple((make_hashable(e) for e in o))
elif isinstance(o, dict):
return tuple(sorted((k, make_hashable(v)) for k, v in o.items()))
elif isinstance(o, (set, frozenset)):
return tuple(sorted(make_hashable(e) for e in o))
return o
class Decoder(json.JSONDecoder):
@ -60,12 +73,21 @@ critical = log_server.critical
#### Variables ####
HOST = ''
PORT = 8888
BUFFER_SIZE = 16384
BUFFER_SIZE = 4096
BEGIN_MESSAGE = bytes("debut".ljust(BUFFER_SIZE, ";"), "ascii")
END_MESSAGE = bytes("fin".ljust(BUFFER_SIZE, ";"), "ascii")
VERSION = "EICP2P2 V1"
DONE = 0
ERROR = 1
#### Socket ####
main_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
main_socket.bind((HOST, PORT))
#### Threads ####
class clientThread(threading.Thread):
"""Main thread, for each client"""
@ -87,14 +109,86 @@ class clientThread(threading.Thread):
self.client = clientsocket
self.ip = ip
self.port = port
self.running = True
self.status = None
debug("Creation du thread pour %s reussie" % ip)
def initialize(self):
"""Interpret request header"""
# Receive message
chunk = bytes("", "ascii")
while chunk != BEGIN_MESSAGE:
chunk = self.client.recv(BUFFER_SIZE)
last_chunk = chunk
while last_chunk != END_MESSAGE:
last_chunk = self.client.recv(BUFFER_SIZE)
chunk += last_chunk
# Remove the begening and the end of chunk
util_part = chunk[BUFFER_SIZE:-BUFFER_SIZE]
print(util_part)
header = util_part[:BUFFER_SIZE]
print(header)
content = util_part[BUFFER_SIZE:]
header_txt = header.decode("ascii").rstrip(";")
version = header_txt.split("\n")[0]
# Extraction des champs du header
if version != VERSION:
debug("Pas la bonne version")
self.send(b"Error".ljust(BUFFER_SIZE, b";"))
champs = {l.split(": ")[0]: l.split(": ")[1] for l in header_txt.split('\n')[1:]}
if champs.get("type", None) is None:
debug("Le champ type n'est pas dans le header")
self.send(b"Error".ljust(BUFFER_SIZE, b";"))
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";"))
return
if champs["type"] == "RSASend":
debug("Réception de la clef RSA de %s", self.ip)
self.rsa_client = content.rstrip(b";").rstrip(b' ')
self.aes_key = get_random_bytes(64)
header = bytes((VERSION+"\ntype: init").ljust(BUFFER_SIZE, "-"), 'ascii')
content = self.aes_key.ljust(BUFFER_SIZE, b";")
self.send_rsa(header+content)
return
def send_rsa(self, to_send):
if self.rsa_client is None:
debug("Clef RSA non recue")
self.client.send(b"Error".ljust(BUFFER_SIZE))
return
# Transform rsakey and generate sessionkey
recipient_key = RSA.import_key(self.rsa_client)
# RSA crypter object
cipher_rsa = PKCS1_OAEP.new(recipient_key)
# Encrypt session_key
self.client.send(BEGIN_MESSAGE)
for to_send_text in [to_send[i:i + BUFFER_SIZE] for i in range(0, len(to_send), BUFFER_SIZE)]:
crypted = b""
for to_send_text_ in [to_send_text[i:i+int(len(self.rsa_client)/16)] for i in range(0, len(to_send_text), int(len(self.rsa_client)/16))]:
print(len(to_send_text_))
crypted += cipher_rsa.encrypt(to_send_text_)
self.client.send(crypted.ljust(BUFFER_SIZE, b';'))
self.client.send(END_MESSAGE)
def send(self, to_send):
self.client.send(BEGIN_MESSAGE)
for to_send_text in [to_send[i:i + BUFFER_SIZE] for i in range(0, len(to_send), BUFFER_SIZE)]:
self.client.send(to_send_text.ljust(BUFFER_SIZE, b";"))
self.client.send(END_MESSAGE)
def run(self): # main de la connection du client
"""Run thread mainloop
:return: Nothing
:rtype: NoneType"""
### ICI ON MET LA BOUCLE PRINCIPALE DE CONNECTION
self.initialize()
print("done")
self.client.close()