Python Language
Sockets et cryptage / décryptage de messages entre le client et le serveur
Recherche…
Introduction
La cryptographie est utilisée à des fins de sécurité. Il n'y a pas beaucoup d'exemples de cryptage / décryptage en Python en utilisant le cryptage MODE CTR IDEA. But de cette documentation:
Étendre et implémenter le schéma de signature numérique RSA dans les communications entre stations. Utiliser Hashing pour l'intégrité du message, c'est SHA-1. Produire un protocole de transport de clé simple. Crypter la clé avec le cryptage IDEA. Le mode de chiffrement de bloc est le mode compteur
Remarques
Langue utilisée: Python 2.7 (lien de téléchargement: https://www.python.org/downloads/ )
Bibliothèque utilisée:
* PyCrypto (lien de téléchargement: https://pypi.python.org/pypi/pycrypto )
* PyCryptoPlus (lien de téléchargement: https://github.com/doegox/python-cryptoplus )
Installation de la bibliothèque:
PyCrypto: Décompressez le fichier. Allez dans le répertoire et ouvrez le terminal pour Linux (alt + ctrl + t) et CMD (shift + clic droit + sélection de l'invite de commande ouverte ici) pour Windows. Après cela, écrivez python setup.py install (Assurez-vous que Python Environment est correctement configuré dans Windows)
PyCryptoPlus: Identique à la dernière bibliothèque.
Tâches Implémentation: La tâche est séparée en deux parties. L'un est un processus de prise de contact et l'autre un processus de communication. Configuration du socket:
Comme la création de clés publiques et privées ainsi que le hachage de la clé publique, nous devons configurer le socket maintenant. Pour configurer le socket, nous devons importer un autre module avec «socket d'importation» et connecter (pour le client) ou lier (pour le serveur) l'adresse IP et le port avec le socket venant de l'utilisateur.
----------Côté client----------
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM) host = raw_input("Server Address To Be Connected -> ") port = int(input("Port of The Server -> ")) server.connect((host, port))
----------Du côté serveur---------
try: #setting up socket server = socket.socket(socket.AF_INET,socket.SOCK_STREAM) server.bind((host,port)) server.listen(5) except BaseException: print "-----Check Server Address or Port-----"
"Socket.AF_INET, socket.SOCK_STREAM" nous permettra d'utiliser la fonction accept () et les fondamentaux de la messagerie. Au lieu de cela, nous pouvons utiliser «socket.AF_INET, socket.SOCK_DGRAM» également, mais cette fois, nous devrons utiliser setblocking (value).
Processus de poignée de main:
- (CLIENT) La première tâche consiste à créer une clé publique et privée. Pour créer la clé privée et publique, nous devons importer certains modules. Ce sont: depuis l'importation Crypto Random et depuis l'importation Crypto.PublicKey RSA. Pour créer les clés, il faut écrire quelques lignes de codes simples:
random_generator = Random.new().read
key = RSA.generate(1024,random_generator)
public = key.publickey().exportKey()
random_generator est dérivé du module " from Crypto import Random ". La clé est dérivée de «à partir de Crypto.PublicKey import RSA » qui créera une clé privée de 1024 en générant des caractères aléatoires. Public exporte la clé publique de la clé privée précédemment générée.
(CLIENT) Après avoir créé la clé publique et privée, nous devons hacher la clé publique pour envoyer au serveur en utilisant le hachage SHA-1. Pour utiliser le hachage SHA-1, nous devons importer un autre module en écrivant «import hashlib». Pour hacher la clé publique, nous avons écrit deux lignes de code:
hash_object = hashlib.sha1(public) hex_digest = hash_object.hexdigest()
Hash_object et hex_digest sont nos variables. Après cela, le client enverra hex_digest et public au serveur et le serveur les vérifiera en comparant le hash obtenu du client et le nouveau hachage de la clé publique. Si le nouveau hachage et le hachage du client correspondent, il passera à la procédure suivante. Comme le public envoyé par le client est sous forme de chaîne, il ne pourra pas être utilisé comme clé du côté serveur. Pour empêcher cela et convertir la clé publique de chaîne en clé publique rsa, nous devons écrire server_public_key = RSA.importKey(getpbk)
, ici getpbk est la clé publique du client.
(SERVER) L'étape suivante consiste à créer une clé de session. Ici, j'ai utilisé le module "os" pour créer une clé aléatoire "key = os.urandom (16)" qui nous donnera une clé de 16 bits et après cela, j'ai chiffré cette clé dans "AES.MODE_CTR" avec SHA-1:
#encrypt CTR MODE session key en = AES.new(key_128,AES.MODE_CTR,counter = lambda:key_128) encrypto = en.encrypt(key_128) #hashing sha1 en_object = hashlib.sha1(encrypto) en_digest = en_object.hexdigest()
Donc, le en_digest sera notre clé de session.
(SERVER) La dernière partie du processus de prise de contact consiste à chiffrer la clé publique obtenue à partir du client et la clé de session créée côté serveur.
#encrypting session key and public key E = server_public_key.encrypt(encrypto,16)
Après le cryptage, le serveur enverra la clé au client sous forme de chaîne.
(CLIENT) Après avoir obtenu la chaîne chiffrée de (clé publique et de session) du serveur, le client les déchiffrera à l'aide de la clé privée créée précédemment avec la clé publique. Comme le crypté (clé publique et clé de session) était sous forme de chaîne, nous devons maintenant le récupérer en tant que clé en utilisant eval (). Si le déchiffrement est effectué, le processus de prise de contact est également terminé, les deux parties confirmant qu'elles utilisent les mêmes clés. Déchiffrer:
en = eval(msg) decrypt = key.decrypt(en) # hashing sha1 en_object = hashlib.sha1(decrypt) en_digest = en_object.hexdigest()
J'ai utilisé le SHA-1 ici pour qu'il soit lisible dans la sortie.
Processus de communication:
Pour le processus de communication, nous devons utiliser la clé de session des deux côtés comme clé pour le cryptage MODE_CTR. Les deux parties vont chiffrer et déchiffrer les messages avec IDEA.MODE_CTR en utilisant la clé de session.
(Cryptage) Pour le cryptage IDEA, nous avons besoin d'une clé de 16 bits et d'un compteur tel que pouvant être appelé. Le compteur est obligatoire dans MODE_CTR. La clé de session que nous avons chiffrée et hachée est désormais de 40, ce qui dépassera la clé de limite du chiffrement IDEA. Par conséquent, nous devons réduire la taille de la clé de session. Pour réduire, nous pouvons utiliser la chaîne de fonctions normale de python intégrée [valeur: valeur]. Où la valeur peut être n'importe quelle valeur en fonction du choix de l'utilisateur. Dans notre cas, j'ai fait “key [: 16]” où il faudra de 0 à 16 valeurs de la clé. Cette conversion pourrait être faite de plusieurs manières comme la clé [1:17] ou la clé [16:]. La prochaine partie consiste à créer une nouvelle fonction de chiffrement IDEA en écrivant IDEA.new () qui prendra trois arguments pour le traitement. Le premier argument sera KEY, le deuxième argument sera le mode de cryptage IDEA (dans notre cas, IDEA.MODE_CTR) et le troisième argument sera le compteur = qui est une fonction appelable. Le compteur = contiendra une taille de chaîne qui sera retournée par la fonction. Pour définir le compteur =, il faut utiliser des valeurs raisonnables. Dans ce cas, j'ai utilisé la taille de la clé en définissant lambda. Au lieu d'utiliser lambda, nous pourrions utiliser Counter.Util qui génère une valeur aléatoire pour le compteur =. Pour utiliser Counter.Util, nous devons importer un module de compteur à partir de crypto. Par conséquent, le code sera:
ideaEncrypt = IDEA.new(key, IDEA.MODE_CTR, counter=lambda : key)
Une fois que vous avez défini «ideaEncrypt» comme variable de chiffrement IDEA, vous pouvez utiliser la fonction de chiffrement intégrée pour chiffrer n'importe quel message.
eMsg = ideaEncrypt.encrypt(whole)
#converting the encrypted message to HEXADECIMAL to readable eMsg =
eMsg.encode("hex").upper()
Dans ce segment de code, tout est le message à chiffrer et eMsg est le message chiffré. Après avoir chiffré le message, je l'ai converti en HEXADECIMAL pour le rendre lisible et upper () est la fonction intégrée pour rendre les caractères en majuscule. Après cela, ce message crypté sera envoyé à la station opposée pour décryptage.
- (Décryptage)
Pour déchiffrer les messages chiffrés, nous devrons créer une autre variable de chiffrement en utilisant les mêmes arguments et la même clé, mais cette fois-ci, la variable déchiffrera les messages chiffrés. Le code pour le même que la dernière fois. Cependant, avant de déchiffrer les messages, nous devons décoder le message en hexadécimal car, dans notre partie chiffrement, nous avons encodé le message chiffré en hexadécimal pour le rendre lisible. Par conséquent, le code entier sera:
decoded = newmess.decode("hex")
ideaDecrypt = IDEA.new(key, IDEA.MODE_CTR, counter=lambda: key)
dMsg = ideaDecrypt.decrypt(decoded)
Ces processus seront effectués côté serveur et côté client pour le cryptage et le décryptage.
Implémentation côté serveur
import socket
import hashlib
import os
import time
import itertools
import threading
import sys
import Crypto.Cipher.AES as AES
from Crypto.PublicKey import RSA
from CryptoPlus.Cipher import IDEA
#server address and port number input from admin
host= raw_input("Server Address - > ")
port = int(input("Port - > "))
#boolean for checking server and port
check = False
done = False
def animate():
for c in itertools.cycle(['....','.......','..........','............']):
if done:
break
sys.stdout.write('\rCHECKING IP ADDRESS AND NOT USED PORT '+c)
sys.stdout.flush()
time.sleep(0.1)
sys.stdout.write('\r -----SERVER STARTED. WAITING FOR CLIENT-----\n')
try:
#setting up socket
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.bind((host,port))
server.listen(5)
check = True
except BaseException:
print "-----Check Server Address or Port-----"
check = False
if check is True:
# server Quit
shutdown = False
# printing "Server Started Message"
thread_load = threading.Thread(target=animate)
thread_load.start()
time.sleep(4)
done = True
#binding client and address
client,address = server.accept()
print ("CLIENT IS CONNECTED. CLIENT'S ADDRESS ->",address)
print ("\n-----WAITING FOR PUBLIC KEY & PUBLIC KEY HASH-----\n")
#client's message(Public Key)
getpbk = client.recv(2048)
#conversion of string to KEY
server_public_key = RSA.importKey(getpbk)
#hashing the public key in server side for validating the hash from client
hash_object = hashlib.sha1(getpbk)
hex_digest = hash_object.hexdigest()
if getpbk != "":
print (getpbk)
client.send("YES")
gethash = client.recv(1024)
print ("\n-----HASH OF PUBLIC KEY----- \n"+gethash)
if hex_digest == gethash:
# creating session key
key_128 = os.urandom(16)
#encrypt CTR MODE session key
en = AES.new(key_128,AES.MODE_CTR,counter = lambda:key_128)
encrypto = en.encrypt(key_128)
#hashing sha1
en_object = hashlib.sha1(encrypto)
en_digest = en_object.hexdigest()
print ("\n-----SESSION KEY-----\n"+en_digest)
#encrypting session key and public key
E = server_public_key.encrypt(encrypto,16)
print ("\n-----ENCRYPTED PUBLIC KEY AND SESSION KEY-----\n"+str(E))
print ("\n-----HANDSHAKE COMPLETE-----")
client.send(str(E))
while True:
#message from client
newmess = client.recv(1024)
#decoding the message from HEXADECIMAL to decrypt the ecrypted version of the message only
decoded = newmess.decode("hex")
#making en_digest(session_key) as the key
key = en_digest[:16]
print ("\nENCRYPTED MESSAGE FROM CLIENT -> "+newmess)
#decrypting message from the client
ideaDecrypt = IDEA.new(key, IDEA.MODE_CTR, counter=lambda: key)
dMsg = ideaDecrypt.decrypt(decoded)
print ("\n**New Message** "+time.ctime(time.time()) +" > "+dMsg+"\n")
mess = raw_input("\nMessage To Client -> ")
if mess != "":
ideaEncrypt = IDEA.new(key, IDEA.MODE_CTR, counter=lambda : key)
eMsg = ideaEncrypt.encrypt(mess)
eMsg = eMsg.encode("hex").upper()
if eMsg != "":
print ("ENCRYPTED MESSAGE TO CLIENT-> " + eMsg)
client.send(eMsg)
client.close()
else:
print ("\n-----PUBLIC KEY HASH DOESNOT MATCH-----\n")
Implémentation côté client
import time
import socket
import threading
import hashlib
import itertools
import sys
from Crypto import Random
from Crypto.PublicKey import RSA
from CryptoPlus.Cipher import IDEA
#animating loading
done = False
def animate():
for c in itertools.cycle(['....','.......','..........','............']):
if done:
break
sys.stdout.write('\rCONFIRMING CONNECTION TO SERVER '+c)
sys.stdout.flush()
time.sleep(0.1)
#public key and private key
random_generator = Random.new().read
key = RSA.generate(1024,random_generator)
public = key.publickey().exportKey()
private = key.exportKey()
#hashing the public key
hash_object = hashlib.sha1(public)
hex_digest = hash_object.hexdigest()
#Setting up socket
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#host and port input user
host = raw_input("Server Address To Be Connected -> ")
port = int(input("Port of The Server -> "))
#binding the address and port
server.connect((host, port))
# printing "Server Started Message"
thread_load = threading.Thread(target=animate)
thread_load.start()
time.sleep(4)
done = True
def send(t,name,key):
mess = raw_input(name + " : ")
key = key[:16]
#merging the message and the name
whole = name+" : "+mess
ideaEncrypt = IDEA.new(key, IDEA.MODE_CTR, counter=lambda : key)
eMsg = ideaEncrypt.encrypt(whole)
#converting the encrypted message to HEXADECIMAL to readable
eMsg = eMsg.encode("hex").upper()
if eMsg != "":
print ("ENCRYPTED MESSAGE TO SERVER-> "+eMsg)
server.send(eMsg)
def recv(t,key):
newmess = server.recv(1024)
print ("\nENCRYPTED MESSAGE FROM SERVER-> " + newmess)
key = key[:16]
decoded = newmess.decode("hex")
ideaDecrypt = IDEA.new(key, IDEA.MODE_CTR, counter=lambda: key)
dMsg = ideaDecrypt.decrypt(decoded)
print ("\n**New Message From Server** " + time.ctime(time.time()) + " : " + dMsg + "\n")
while True:
server.send(public)
confirm = server.recv(1024)
if confirm == "YES":
server.send(hex_digest)
#connected msg
msg = server.recv(1024)
en = eval(msg)
decrypt = key.decrypt(en)
# hashing sha1
en_object = hashlib.sha1(decrypt)
en_digest = en_object.hexdigest()
print ("\n-----ENCRYPTED PUBLIC KEY AND SESSION KEY FROM SERVER-----")
print (msg)
print ("\n-----DECRYPTED SESSION KEY-----")
print (en_digest)
print ("\n-----HANDSHAKE COMPLETE-----\n")
alais = raw_input("\nYour Name -> ")
while True:
thread_send = threading.Thread(target=send,args=("------Sending Message------",alais,en_digest))
thread_recv = threading.Thread(target=recv,args=("------Recieving Message------",en_digest))
thread_send.start()
thread_recv.start()
thread_send.join()
thread_recv.join()
time.sleep(0.5)
time.sleep(60)
server.close()