Communication secrète
Comment implémenter une application de communication secrète pour échanger des messages chiffrés
À la cryptographie, c’est mon domaine préféré, et vous êtes bien tombé car ici, nous allons établir un canal de communication secret entre deux machines pour qu’elles communiquent sans que personne entre les deux ne puisse intercepter le message en clair, ou voler la clé de chiffrement !
Introduction au Chiffrement Symétrique
Le chiffrement symétrique est une méthode de chiffrement où la même clé est utilisée pour chiffrer et déchiffrer les données. Cette clé doit être partagée entre les parties communicantes de manière sécurisée. Parmi les algorithmes de chiffrement symétrique les plus populaires, on trouve AES (Advanced Encryption Standard).
Comprendre AES CBC
AES (Advanced Encryption Standard) est un algorithme de chiffrement symétrique largement utilisé dans la sécurisation des données. Il fonctionne sur des blocs de données de 128 bits (16 octets) et peut utiliser des clés de 128, 192 ou 256 bits. AES CBC (Cipher Block Chaining) est un mode d'opération pour AES qui permet de chiffrer des blocs de données de manière plus sécurisée en utilisant un vecteur d'initialisation (IV) unique pour chaque message.
Dans le mode CBC, chaque bloc de texte en clair est XORé avec le bloc de texte chiffré précédent avant d'être chiffré. Cela signifie que chaque bloc chiffré dépend de tous les blocs précédents, ce qui rend le chiffrement plus résistant aux attaques par analyse statistique.
Comprendre Les communications entre sockets TCP entre deux serveur
Les communications entre sockets TCP entre deux serveurs permettent l'échange fiable et ordonné de données sur un réseau. Chaque serveur écoute sur un port spécifique pour les connexions entrantes et utilise des sockets pour envoyer et recevoir des messages. Lorsqu'une connexion est établie, les données peuvent être transférées de manière bidirectionnelle, garantissant que chaque octet envoyé est reçu dans le même ordre. Cette fiabilité et cette intégrité de transmission sont essentielles pour des applications telles que la messagerie sécurisée et les transactions financières.
Implémentation du Chiffrement AES CBC en Python
Voici un guide étape par étape pour implémenter un système de communication chiffré en utilisant AES CBC en Python.
Étape 1: Installation des Pré-requis
Avant de commencer, vous devez installer le module pycryptodome
, qui fournit les primitives de chiffrement nécessaires.
# Créez et activez un environnement virtuel
python3 -m venv venv
source venv/bin/activate
# Installez pycryptodome
pip install pycryptodome
Étape 2: Écriture du Code de Chiffrement et Déchiffrement
Le code suivant vous montre comment chiffrer et déchiffrer des messages en utilisant AES CBC.
import base64
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
from Crypto.Random import get_random_bytes
def encrypt_message(message, key, iv):
cipher = AES.new(key, AES.MODE_CBC, iv)
ct_bytes = cipher.encrypt(pad(message.encode(), AES.block_size))
return base64.b64encode(cipher.iv + ct_bytes).decode('utf-8')
def decrypt_message(encrypted_message, key):
try:
encrypted_message = base64.b64decode(encrypted_message)
iv = encrypted_message[:AES.block_size]
ct = encrypted_message[AES.block_size:]
cipher = AES.new(key, AES.MODE_CBC, iv)
pt = unpad(cipher.decrypt(ct), AES.block_size)
return pt.decode('utf-8')
except Exception as e:
print("Une erreur lors du déchiffrement du message reçu...")
print("Avez-vous la même clé secrète des deux côtés de la communication ?")
Étape 3: Création des Fonctions Serveur et Client
Le code suivant configure un serveur et un client pour envoyer et recevoir des messages chiffrés.
import socket
import threading
import time
def start_server(local_ip, local_port, key):
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((local_ip, local_port))
server.listen(1)
print(f"Listening on {local_ip}:{local_port}")
client_socket, addr = server.accept()
print(f"Accepted connection from {addr}")
while True:
encrypted_message = client_socket.recv(1024).decode('utf-8')
if not encrypted_message:
print("Connection closed.")
break
decrypted_message = decrypt_message(encrypted_message, key)
print(f"<<<< Received: {decrypted_message}")
message = input("Enter message to send: ")
iv = get_random_bytes(AES.block_size)
encrypted_message = encrypt_message(message, key, iv)
client_socket.send(encrypted_message.encode('utf-8'))
client_socket.close()
def start_client(remote_ip, remote_port, key):
while True:
try:
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((remote_ip, remote_port))
print(f"Connected to {remote_ip}:{remote_port}")
while True:
message = input("Enter message to send: ")
iv = get_random_bytes(AES.block_size)
encrypted_message = encrypt_message(message, key, iv)
client.send(encrypted_message.encode('utf-8'))
encrypted_message = client.recv(1024).decode('utf-8')
if not encrypted_message:
print("Connection closed.")
break
decrypted_message = decrypt_message(encrypted_message, key)
print(f"<<<< Received: {decrypted_message}")
client.close()
except Exception as e:
print("Tentative de connexion au serveur distant échouée.")
time.sleep(2)
Étape 4: Démarrage du Serveur et du Client
Pour démarrer le serveur et le client, utilisez le code suivant. Assurez-vous de fournir les bonnes adresses IP et ports, ainsi qu'une clé secrète valide (16, 24 ou 32 octets).
if __name__ == "__main__":
remote_ip = input("Enter remote server IP address: ")
remote_port = int(input("Enter remote server port: "))
local_port = int(input("Enter local server port: "))
secret_key = input("Enter secret key (must be 16, 24, or 32 bytes long): ").encode()
if len(secret_key) not in {16, 24, 32}:
raise ValueError("Key must be 16, 24, or 32 bytes long")
local_ip = '0.0.0.0' # Listen on all interfaces
server_thread = threading.Thread(target=start_server, args=(local_ip, local_port, secret_key))
server_thread.start()
start_client(remote_ip, remote_port, secret_key)
Le chiffrement symétrique avec AES CBC offre une manière robuste de sécuriser les communications. En suivant les étapes décrites ci-dessus, vous pouvez implémenter un système de communication chiffré en Python. Assurez-vous toujours de garder votre clé secrète sécurisée et de ne la partager qu'avec des parties de confiance.
N’utilisez pas cette technique à des fins malveillantes.
Ici, personne ne pourra voir vos messages, ni WhatsApp, ni Telegram, ni l’hébergeur de votre serveur.
Votre communication sera vraiment secrète et connue uniquement de vous et de la personne avec qui vous communiquez, faites en bon usage.
Ce code est déclinable de plusieurs manières possibles:
Chiffrer/déchiffrer des fichiers texte
Chiffrer/déchiffrer des images
Via une socket TCP, vous pouvez envoyer ce que vous souhaitez, ce ne sont que des bytes qui passent par le réseau.
Ci-dessous le code Python complet.
# Des deux cotés de la communication, il faut installer le module pycryptodome
# python3 -m venv venv
# source venv/bin/activate
# pip install pycryptodome
# python main.py
# D'un cote, utiliser ses parametre
# Enter remote server IP address: 127.0.0.1
# Enter remote server port: 8000
# Enter local server port: 9000
# Enter secret key (must be 16, 24, or 32 bytes long): passwordpassword
# De l'autre cote, utiliser ses parametre
# Enter remote server IP address: 127.0.0.1
# Enter remote server port: 9000
# Enter local server port: 8000
# Enter secret key (must be 16, 24, or 32 bytes long): passwordpassword
# La communication chiffrée est établie entre les deux cotés
# vous pouvez envoyer des messages chiffrés entre les deux cotés depuis un machine local sur l'ip 127.0.0.1
# vous pouvez envoyer des messages chiffrés entre les deux cotés depuis un vps en parametrant l'ip du vps distant que vous voulai joindre et le port qui sera ouvert sur le vps distant
import socket
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
from Crypto.Random import get_random_bytes
import base64
import time
import threading
def encrypt_message(message, key, iv):
cipher = AES.new(key, AES.MODE_CBC, iv)
ct_bytes = cipher.encrypt(pad(message.encode(), AES.block_size))
return base64.b64encode(cipher.iv + ct_bytes).decode('utf-8')
def decrypt_message(encrypted_message, key):
try:
encrypted_message = base64.b64decode(encrypted_message)
iv = encrypted_message[:AES.block_size]
ct = encrypted_message[AES.block_size:]
cipher = AES.new(key, AES.MODE_CBC, iv)
pt = unpad(cipher.decrypt(ct), AES.block_size)
return pt.decode('utf-8')
except Exception as e:
print("Une erreur lors du déchifrement du message recu...")
print("Avez vous la meme clée secrete des deux coté de la communication ?")
def start_server(local_ip, local_port, key):
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((local_ip, local_port))
server.listen(1)
print(f"Listening on {local_ip}:{local_port}")
client_socket, addr = server.accept()
print(f"Accepted connection from {addr}")
while True:
encrypted_message = client_socket.recv(1024).decode('utf-8')
if not encrypted_message:
print("Connection closed.")
break
decrypted_message = decrypt_message(encrypted_message, key)
print(f"<<<< Received: {decrypted_message}")
message = input("Enter message to send: ")
iv = get_random_bytes(AES.block_size)
encrypted_message = encrypt_message(message, key, iv)
client_socket.send(encrypted_message.encode('utf-8'))
client_socket.close()
def start_client(remote_ip, remote_port, key):
while True:
try:
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((remote_ip, remote_port))
print(f"Connected to {remote_ip}:{remote_port}")
while True:
message = input("Enter message to send: ")
iv = get_random_bytes(AES.block_size)
encrypted_message = encrypt_message(message, key, iv)
client.send(encrypted_message.encode('utf-8'))
encrypted_message = client.recv(1024).decode('utf-8')
if not encrypted_message:
print("Connection closed.")
break
decrypted_message = decrypt_message(encrypted_message, key)
print(f"<<<< Received: {decrypted_message}")
client.close()
except Exception as e:
print("Tentative de connexion au serveur distant échouée.")
time.sleep(2)
if __name__ == "__main__":
remote_ip = input("Enter remote server IP address: ")
remote_port = int(input("Enter remote server port: "))
local_port = int(input("Enter local server port: "))
secret_key = input("Enter secret key (must be 16, 24, or 32 bytes long): ").encode()
if len(secret_key) not in {16, 24, 32}:
raise ValueError("Key must be 16, 24, or 32 bytes long")
local_ip = '0.0.0.0' # Listen on all interfaces
server_thread = threading.Thread(target=start_server, args=(local_ip, local_port, secret_key))
server_thread.start()
start_client(remote_ip, remote_port, secret_key)
Dans la prochaine newsletter, tu apprendras comment fonctionne un virus informatique.
J’ai écrit un post Linkedin sur les virus et comment en créer un, mais il a été censuré sur Linkedin, donc il est en exclusivité dans cette newsletter.
Bien que, je rentre davantage dans les détails au sujet des virus et de comment en créer, au travers de LaFormationCyber qui commence en septembre.
Vous aurai une petite idée de comment fonctionne ces programmes qui peuvent être redoutable en lisant la newsletter de la semaine prochaine.
Le virus sera codé en Python.
Même après ce que tu viens de lire, tu ne connais pas Python ? LearnPython.
À la semaine prochaine, Neo.
Tu aimerais te former à la cybersécurité pour devenir un hacker éthique ou le Cybersecurity Champion de ton équipe ?
Rejoins ma formation spécialisée en hacking en cliquant ici.
Il ne reste que 14 places disponibles en prévente pour un démarrage en septembre 2024.