Python Language
Сокеты и шифрование / расшифровка сообщений между клиентом и сервером
Поиск…
Вступление
Криптография используется в целях безопасности. Существует не так много примеров шифрования / дешифрования в Python, использующих CREATE CREATE IDEA. Цель этой документации:
Расширение и внедрение схемы цифровой подписи RSA в связи между станциями. Использование Hash для целостности сообщения, то есть SHA-1. Создайте простой протокол передачи ключей. Шифровать ключ с помощью кода IDEA. Режим блочного шифрования - режим счетчика
замечания
Используемый язык: Python 2.7 (ссылка для загрузки: https://www.python.org/downloads/ )
Используемая библиотека:
* PyCrypto (ссылка для загрузки: https://pypi.python.org/pypi/pycrypto )
* PyCryptoPlus (ссылка для скачивания: https://github.com/doegox/python-cryptoplus )
Установка библиотеки:
PyCrypto: разархивируйте файл. Перейдите в каталог и откройте терминал для linux (alt + ctrl + t) и CMD (сдвиньте + правый щелчок + выберите командную строку, открытую здесь) для окон. После этого напишите python setup.py install (Make Sure Python Environment правильно настроена в ОС Windows)
PyCryptoPlus: такая же, как и последняя библиотека.
Выполнение задач: задача разделяется на две части. Один из них - процесс рукопожатия, а другой - процесс коммуникации. Настройка гнезда:
Как создание открытых и закрытых ключей, а также хэширование открытого ключа, нам нужно настроить сокет сейчас. Для настройки сокета нам нужно импортировать другой модуль со «импортным сокетом» и подключить (для клиента) или связать (для сервера) IP-адрес и порт с получением сокета от пользователя.
----------Сторона клиента----------
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))
---------- Серверная сторона ---------
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» позволит нам использовать функцию accept () и основные принципы обмена сообщениями. Вместо этого мы можем использовать «socket.AF_INET, socket.SOCK_DGRAM», но в то же время нам придется использовать setblocking (значение).
Процесс рукопожатия:
- (КЛИЕНТ) Первой задачей является создание открытого и закрытого ключа. Чтобы создать закрытый и открытый ключ, нам нужно импортировать некоторые модули. Это: из Crypto import Random и из Crypto.PublicKey import RSA. Чтобы создать ключи, нам нужно написать несколько простых строк кодов:
random_generator = Random.new().read
key = RSA.generate(1024,random_generator)
public = key.publickey().exportKey()
random_generator получен из модуля « из Crypto import Random ». Ключ получен из « из Crypto.PublicKey import RSA », который создаст закрытый ключ размером 1024, генерируя случайные символы. Публикация экспортирует открытый ключ из ранее сгенерированного закрытого ключа.
(CLIENT). После создания открытого и закрытого ключа мы должны использовать хэш для открытого ключа для отправки на сервер с использованием хэша SHA-1. Чтобы использовать хэш SHA-1, нам нужно импортировать другой модуль, написав «import hashlib». Для хэш-ключа мы пишем две строки кода:
hash_object = hashlib.sha1(public) hex_digest = hash_object.hexdigest()
Здесь hash_object и hex_digest - наша переменная. После этого клиент отправит hex_digest и public на сервер, и сервер проверит их, сравнив хэш с клиентом и новый хэш открытого ключа. Если новый хеш и хэш от клиента совпадают, он перейдет к следующей процедуре. Поскольку публикация, отправленная от клиента, имеет форму строки, она не сможет использоваться как ключ на стороне сервера. Чтобы предотвратить это и преобразовать открытый ключ строки в открытый ключ rsa, нам нужно написать server_public_key = RSA.importKey(getpbk)
, здесь getpbk - это открытый ключ от клиента.
(SERVER) Следующий шаг - создать ключ сеанса. Здесь я использовал модуль «os» для создания случайного ключа «key = os.urandom (16)», который даст нам 16-битный длинный ключ, после чего я зашифровал этот ключ в «AES.MODE_CTR» и снова хешу с 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()
Таким образом, en_digest будет нашим ключом сеанса.
(SERVER) Для окончательной части процесса рукопожатия необходимо зашифровать открытый ключ, полученный от клиента, и ключ сеанса, созданный на стороне сервера.
#encrypting session key and public key E = server_public_key.encrypt(encrypto,16)
После шифрования сервер отправит ключ клиенту в виде строки.
(CLIENT) После получения зашифрованной строки (открытого и сеансового ключа) с сервера клиент расшифрует их с помощью Private Key, который был создан ранее вместе с открытым ключом. Поскольку зашифрованный (открытый и сеансовый ключ) был в форме строки, теперь мы должны вернуть его в качестве ключа, используя eval (). Если дешифрование завершено, процесс рукопожатия завершается также, когда обе стороны подтверждают, что используют одни и те же ключи. Чтобы расшифровать:
en = eval(msg) decrypt = key.decrypt(en) # hashing sha1 en_object = hashlib.sha1(decrypt) en_digest = en_object.hexdigest()
Я использовал SHA-1 здесь, чтобы он был доступен для чтения на выходе.
Процесс коммуникации:
Для коммуникационного процесса мы должны использовать ключ сеанса с обеих сторон в качестве ключа для кодирования IDEA MODE_CTR. Обе стороны будут шифровать и дешифровать сообщения с помощью IDEA.MODE_CTR, используя ключ сеанса.
(Шифрование) Для шифрования IDEA нам нужен ключ размером 16 бит и счетчик, который должен быть вызван. Счетчик является обязательным в MODE_CTR. Ключ сеанса, который мы зашифровали и хешировал, теперь имеет размер 40, который будет превышать предельный ключ шифрования IDEA. Следовательно, нам нужно уменьшить размер ключа сеанса. Для сокращения мы можем использовать обычный питон, встроенный в строку функций [значение: значение]. Если значение может быть любым значением в соответствии с выбором пользователя. В нашем случае я сделал «key [: 16]», где от ключа будет от 0 до 16 значений. Это преобразование можно было бы сделать многими способами, такими как клавиша [1:17] или клавиша [16:]. Следующая часть - создать новую функцию шифрования IDEA, написав IDEA.new (), которая будет принимать 3 аргумента для обработки. Первым аргументом будет KEY, вторым аргументом будет режим шифрования IDEA (в нашем случае IDEA.MODE_CTR), а третьим аргументом будет счетчик = который является обязательной вызываемой функцией. Счетчик = будет содержать размер строки, который будет возвращен функцией. Чтобы определить счетчик =, мы должны использовать разумные значения. В этом случае я использовал размер KEY, определяя лямбда. Вместо использования лямбда мы могли бы использовать Counter.Util, который генерирует случайное значение для counter =. Чтобы использовать Counter.Util, нам нужно импортировать модуль счетчика из crypto. Следовательно, код будет:
ideaEncrypt = IDEA.new(key, IDEA.MODE_CTR, counter=lambda : key)
Определив «ideaEncrypt» как нашу переменную шифрования IDEA, мы можем использовать встроенную функцию шифрования для шифрования любого сообщения.
eMsg = ideaEncrypt.encrypt(whole)
#converting the encrypted message to HEXADECIMAL to readable eMsg =
eMsg.encode("hex").upper()
В этом сегменте кода целое является зашифрованным сообщением, а eMsg является зашифрованным сообщением. После шифрования сообщения я преобразовал его в HEXADECIMAL, чтобы сделать readable и upper () - встроенной функцией, чтобы сделать символы в верхнем регистре. После этого это зашифрованное сообщение будет отправлено на противоположную станцию для дешифрования.
- (Дешифрование)
Чтобы расшифровать зашифрованные сообщения, нам нужно будет создать другую переменную шифрования, используя те же аргументы и тот же ключ, но на этот раз переменная расшифрует зашифрованные сообщения. Код для этого же, как и в последний раз. Однако перед расшифровкой сообщений нам нужно декодировать сообщение из шестнадцатеричного числа, поскольку в нашей части шифрования мы закодировали зашифрованное сообщение в шестнадцатеричном виде, чтобы сделать чтение. Следовательно, весь код будет:
decoded = newmess.decode("hex")
ideaDecrypt = IDEA.new(key, IDEA.MODE_CTR, counter=lambda: key)
dMsg = ideaDecrypt.decrypt(decoded)
Эти процессы будут выполняться как на стороне сервера, так и на стороне клиента для шифрования и дешифрования.
Реализация на стороне сервера
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")
Реализация клиентской стороны
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()