Python Language
Socket e crittografia / decrittografia dei messaggi tra client e server
Ricerca…
introduzione
La crittografia viene utilizzata per motivi di sicurezza. Non ci sono molti esempi di crittografia / decodifica in Python utilizzando CTR di codifica IDEA di crittografia. Scopo di questa documentazione:
Estendere e implementare lo schema RSA Digital Signature nella comunicazione da stazione a stazione. Utilizzando l'hashing per l'integrità del messaggio, questo è SHA-1. Produce un semplice protocollo Key Transport. Cripta chiave con crittografia IDEA. La modalità di Block Cipher è Counter Mode
Osservazioni
Lingua utilizzata: Python 2.7 (Link per il download: https://www.python.org/downloads/ )
Libreria utilizzata:
* PyCrypto (Link per il download: https://pypi.python.org/pypi/pycrypto )
* PyCryptoPlus (Link per il download: https://github.com/doegox/python-cryptoplus )
Installazione della libreria:
PyCrypto: decomprimere il file. Vai alla directory e apri il terminale per linux (alt + ctrl + t) e CMD (shift + tasto destro + seleziona prompt dei comandi aperto qui) per windows. Dopodiché scrivi python setup.py install (Make Sure Python Environment è impostato correttamente nel sistema operativo Windows)
PyCryptoPlus: come l'ultima libreria.
Implementazione delle attività: l'attività è suddivisa in due parti. Uno è il processo di handshake e un altro è il processo di comunicazione. Impostazione socket:
Come la creazione di chiavi pubbliche e private e l'hashing della chiave pubblica, ora dobbiamo configurare il socket. Per configurare il socket, dobbiamo importare un altro modulo con "import socket" e connettere (per client) o bind (per server) l'indirizzo IP e la porta con il socket che viene prelevato dall'utente.
----------Dalla parte del cliente----------
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))
----------Lato server---------
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" ci consentirà di utilizzare la funzione accept () e i fondamentali della messaggistica. Invece, possiamo usare "socket.AF_INET, socket.SOCK_DGRAM" anche se questa volta dovremo usare il setblocking (valore).
Processo di handshake:
- (CLIENT) Il primo compito è creare una chiave pubblica e privata. Per creare la chiave privata e pubblica, dobbiamo importare alcuni moduli. Sono: da Crypto import Random e da Crypto.PublicKey import RSA. Per creare le chiavi, dobbiamo scrivere poche semplici righe di codici:
random_generator = Random.new().read
key = RSA.generate(1024,random_generator)
public = key.publickey().exportKey()
random_generator è derivato dal modulo " from Crypto import Random ". La chiave è derivata da " da Crypto.PublicKey import RSA " che creerà una chiave privata, dimensione di 1024 generando caratteri casuali. Il pubblico sta esportando la chiave pubblica dalla chiave privata precedentemente generata.
(CLIENT) Dopo aver creato la chiave pubblica e privata, dobbiamo hash la chiave pubblica da inviare al server usando l'hash SHA-1. Per usare l'hash SHA-1 dobbiamo importare un altro modulo scrivendo "import hashlib". Per cancellare la chiave pubblica abbiamo scritto due righe di codice:
hash_object = hashlib.sha1(public) hex_digest = hash_object.hexdigest()
Qui hash_object e hex_digest è la nostra variabile. Dopodiché, il client invierà hex_digest e pubblico al server e Server li verificherà confrontando l'hash ottenuto dal client e il nuovo hash della chiave pubblica. Se il nuovo hash e l'hash del client corrispondono, passerà alla procedura successiva. Dato che il pubblico inviato dal client è in forma di stringa, non potrà essere utilizzato come chiave sul lato server. Per evitare ciò e convertire la chiave pubblica stringa in chiave pubblica rsa, dobbiamo scrivere server_public_key = RSA.importKey(getpbk)
, qui getpbk è la chiave pubblica del client.
(SERVER) Il prossimo passo è creare una chiave di sessione. Qui, ho usato il modulo "os" per creare una chiave casuale "key = os.urandom (16)" che ci darà una chiave lunga 16 bit e dopo di che ho crittografato quella chiave in "AES.MODE_CTR" e l'ho cancellato di nuovo con 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()
Quindi en_digest sarà la nostra chiave di sessione.
(SERVER) Per la parte finale del processo di handshake è necessario crittografare la chiave pubblica ricevuta dal client e la chiave di sessione creata sul lato server.
#encrypting session key and public key E = server_public_key.encrypt(encrypto,16)
Dopo la crittografia, il server invierà la chiave al client come stringa.
(CLIENT) Dopo aver ottenuto la stringa crittografata di (chiave pubblica e di sessione) dal server, il client la decrittografa utilizzando la chiave privata che è stata creata in precedenza insieme alla chiave pubblica. Dato che la chiave crittografata (pubblica e di sessione) era in forma di stringa, ora dobbiamo recuperarla come chiave utilizzando eval (). Se la decrittografia è stata eseguita, il processo di handshake è completato anche quando entrambi i lati confermano che stanno utilizzando le stesse chiavi. Per decifrare:
en = eval(msg) decrypt = key.decrypt(en) # hashing sha1 en_object = hashlib.sha1(decrypt) en_digest = en_object.hexdigest()
Ho usato lo SHA-1 qui in modo che sia leggibile nell'output.
Processo di comunicazione:
Per il processo di comunicazione, dobbiamo utilizzare la chiave di sessione da entrambi i lati come KEY per la crittografia IDEA MODE_CTR. Entrambe le parti cripteranno e decodificheranno i messaggi con IDEA.MODE_CTR utilizzando la chiave di sessione.
(Crittografia) Per la crittografia IDEA, abbiamo bisogno di una chiave di 16 bit in dimensioni e contatore come deve essere richiamabile. Il contatore è obbligatorio in MODE_CTR. La chiave di sessione che abbiamo crittografato e con hash è ora una dimensione di 40 che supererà la chiave di limite della crittografia IDEA. Quindi, abbiamo bisogno di ridurre la dimensione della chiave di sessione. Per la riduzione, possiamo usare la normale stringa di funzione python incorporata [valore: valore]. Dove il valore può essere qualsiasi valore in base alla scelta dell'utente. Nel nostro caso, ho fatto "key [: 16]" dove ci vorranno da 0 a 16 valori dalla chiave. Questa conversione può essere eseguita in molti modi come chiave [1:17] o chiave [16:]. La parte successiva è creare una nuova funzione di crittografia IDEA scrivendo IDEA.new () che richiederà 3 argomenti per l'elaborazione. Il primo argomento sarà KEY, il secondo argomento sarà la modalità della crittografia IDEA (nel nostro caso, IDEA.MODE_CTR) e il terzo argomento sarà il counter = che è una funzione callable obbligatoria. Il contatore = manterrà una dimensione di stringa che verrà restituita dalla funzione. Per definire il contatore =, dobbiamo usare valori ragionevoli. In questo caso, ho usato la dimensione della KEY definendo lambda. Invece di usare lambda, potremmo usare Counter.Util che genera un valore casuale per counter =. Per utilizzare Counter.Util, è necessario importare il modulo contatore da crypto. Quindi, il codice sarà:
ideaEncrypt = IDEA.new(key, IDEA.MODE_CTR, counter=lambda : key)
Una volta che definiamo "ideaEncrypt" come la nostra variabile di crittografia IDEA, possiamo usare la funzione di crittografia integrata per crittografare qualsiasi messaggio.
eMsg = ideaEncrypt.encrypt(whole)
#converting the encrypted message to HEXADECIMAL to readable eMsg =
eMsg.encode("hex").upper()
In questo segmento di codice, intero è il messaggio da crittografare e eMsg è il messaggio crittografato. Dopo aver crittografato il messaggio, l'ho convertito in HEXADECIMAL per renderlo leggibile e upper () è la funzione incorporata per rendere i caratteri maiuscoli. Successivamente, questo messaggio crittografato verrà inviato alla stazione opposta per la decrittografia.
- (Decodificazione)
Per decodificare i messaggi crittografati, sarà necessario creare un'altra variabile di crittografia utilizzando gli stessi argomenti e la stessa chiave, ma questa volta la variabile decodificherà i messaggi crittografati. Il codice per questo come l'ultima volta. Tuttavia, prima di decifrare i messaggi, abbiamo bisogno di decodificare il messaggio da esadecimale perché nella nostra parte di crittografia abbiamo codificato il messaggio crittografato in esadecimale per renderlo leggibile. Quindi, l'intero codice sarà:
decoded = newmess.decode("hex")
ideaDecrypt = IDEA.new(key, IDEA.MODE_CTR, counter=lambda: key)
dMsg = ideaDecrypt.decrypt(decoded)
Questi processi saranno eseguiti sia lato server che lato client per la crittografia e la decrittografia.
Implementazione lato server
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")
Implementazione lato 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()