Алгоритм RSA на PYTHON
moderator E7
Всем привет ! Сегодня я расскажу и покажу очень популярный алгоритм ассиметричного шифрования- RSA.
Реализуем это на Python с использованием модулей.
Предисловие
Прежде чем начну, хочу сказать пару слов о видах шифрования.
- Симметричное
- Ассиметричное

Симметричное - это такой тип шифрования, суть которого заключается в том, что при шифровании и дешифровании используется один и тот же ключ. Криптосистемы, они же так называемые шифры , имеют разную по своей сути шифрование данных, а если и шифрование разное , то и криптографические ключи тоже отличаются.
Вот парочка шифров:
- Шифр Цезаря - один из самых известных , в первую очередь из-за большого распространения в медиа-культуре. Ключом является число сдвига каждого символа шифруемых данных.
- Шифр Виженера - не менее популярный шифр, суть алгоритма проста - это последовательность шифров Цезаря с различными значениями сдвига.
Пишем алгоритм RSA
Мы узнали, что такое симметричное шифрование, пришло время перейти к алгоритму RSA, который в свою очередь относится к ассиметричному шифрованию. Пару слов о нём:
Асимметричное шифрование - это метод шифрования данных, предполагающий использование двух ключей - открытого и закрытого. Открытый (public) ключ применяется для шифрования информации, и может передаваться по незащищенным каналам. Закрытый (private) ключ применяется для расшифровки данных, зашифрованных открытым ключом. Открытый и закрытый ключи — это очень большие числа, связанные друг с другом определенной функцией, но так, что, зная одно, крайне сложно вычислить второе.
Параллельно с алгоритмом , мы напишем свой консольный чат с помощью модуля socket:
1 - Сервер

import socket
with socket.socket(socket.AF_INET , socket.SOCK_STREAM) as server:
#bind the socket to address
server.bind(("127.0.0.1", 1337))
#listen channel
server.listen()
#accepts client-socket
client, client_addr = server.accept()
while True:
#input message and convert to bytes
msg = input("server >> ").encode("utf-8")
#send to client.py
client.sendall(msg)
#received bytes and convert to string again
data_received = client.recv(128)
print("user :: " + data_received.decode("utf-8"))
На стороне сервера будет развёрнута криптосистема , но пока что сделаем клиента.
Стоит сразу упомянуть , чтобы вы акцентировали внимание на RSA , я не буду усложнять чат введением в него асинхронного кода.
А теперь давайте напишем клиента:
2 - Клиент

import socket
#create server-socket
with socket.socket(socket.AF_INET , socket.SOCK_STREAM) as server:
#listen and connect to ip 127.0.0.1 and port 1337
server.connect(("127.0.0.1" , 1337))
while True:
#received massive bytes from server
data_received = server.recv(64)
#output in terminal
print("server :: "+ data_received.decode("utf-8"))
#input and convert string to bytess
msg = input("ME >> ").encode("utf-8")
#send data to server
server.sendall(msg)
3 - RSA
На данном этапе я встрою в наш код RSA-алгоритм для передачи зашифрованной информации, в этом деле мне поможет модуль rsa.


import rsa
def generate_keys():
(pubKey, privKey) = rsa.newkeys(1024)
with open('keys/pubkey.pem', 'wb') as f:
f.write(pubKey.save_pkcs1('PEM'))
with open('keys/privkey.pem', 'wb') as f:
f.write(privKey.save_pkcs1('PEM'))
def load_keys():
with open('keys/pubkey.pem', 'rb') as f:
pubKey = rsa.PublicKey.load_pkcs1(f.read())
with open('keys/privkey.pem', 'rb') as f:
privKey = rsa.PrivateKey.load_pkcs1(f.read())
return pubKey, privKey
def encrypt(msg, key):
return rsa.encrypt(msg.encode('ascii'), key)
def decrypt(ciphertext, key):
try:
return rsa.decrypt(ciphertext, key).decode('ascii')
except:
return False
def sign_sha1(msg, key):
return rsa.sign(msg.encode('ascii'), key, 'SHA-1')
def verify_sha1(msg, signature, key):
try:
return rsa.verify(msg.encode('ascii'), signature, key) == 'SHA-1'
except:
return False
generate_keys()
pubKey, privKey = load_keys()
message = input('Enter a message:')
ciphertext = encrypt(message, pubKey)
signature = sign_sha1(message, privKey)
plaintext = decrypt(ciphertext, privKey)
print(f'Cipher text: {ciphertext}')
print(f'Signature: {signature}')
if plaintext:
print(f'Plain text: {plaintext}')
else:
print('Could not decrypt the message.')
if verify_sha1(plaintext, signature, pubKey):
print('Signature verified!')
else:
print('Could not verify the message signature.')
Сейчас я постараюсь объяснить как работает этот алгоритм.
Теперь представим следующую ситуацию. Есть Алиса, и есть Боб. Они сверхсекретные агенты, и они не могут выдать то, о чем они болтают между собой, и какие сверхсекретные данные передают. Алиса сидит на телефоне, Боб сидит на другом конце телефона а посередине сидит их общий заклятый враг и внимательно слушает, о чем они говорят. Алисе надо передать Бобу очень секретное число, но просто сказать по телефону она ему не может — враг не дремлет.
- Алиса спрашивает у Боба открытый ключ, он ей говорит его по телефону. Ключ становится известен всем, в том числе не только Алисе, но и еще тому, кто сидит и слушает их
- Алиса берет это число (открытый ключ), производит определенные действия над тем числом, что хочет закодировать и отсылает Бобу. Человек посередине эту информацию тоже перехватил.
- Боб же берет закрытый ключ, который он создал вместе с открытым и производя математические действия, расшифровывает число Алисы
- Человек посередине не знает закрытого ключа Боба, а по открытому ключу он не может ничего сделать, потому что расшифровать сообщение можно только с помощью закрытого. Человек с досады кусает свои локти.
Вкратце:
- Боб создает открытый и закрытый ключи (они взаимосвязаны, как Том и Джерри)
- Алиса получает открытый ключ Боба
- Кодирует с его помощью свое число
- Отсылает число по небезопасному каналу связи
- Боб расшифровывает число с помощью закрытого ключа
Более абстрактно:
- Создать открытый и закрытый ключи
- Передать открытый ключ тому, кто будет шифровать
- Зашифровать сообщение с помощью открытого ключа
- Передать зашифрованное сообщение по каналу связи
- Расшифровать сообщение с помощью закрытого ключа
Задача !
А теперь задача для читателя ! Вам будет необходимо дописать код чата, дополнив его алгоритмом RSA, написанным ранее.
С любовью от E7TEAM ;)