Я кодирую сообщение с помощью rsa.encrypt
, но затем не могу преобразовать зашифрованные данные в str
с помощью .decode()
.
Это немного странно, потому что зашифрованные данные представляют собой строку байтов, и не должно возникнуть проблем с преобразованием ее в str
.
data = [self.id, data, self.my_pubkey] # actually don't care about type of components, they are correct
Мой код:
import json
import rsa
def msg(query_type, data):
if query_type == 'PubKey':
try:
query = {"Type": "PubKey",
"Message": {"PubKey": data[0],
"Id": data[1]
}
}
to_send = json.dumps(query)
to_send = to_send.encode()
return to_send
except Exception as ex:
print("Error in creating message")
print(ex)
elif query_type == 'Message':
try:
encrypted_data = rsa.encrypt(data[1].encode('utf-8'), data[2])
print(encrypted_data.decode('utf-8'))
query = {"Type": "Message",
"Message": {"Id": data[0],
"Data": str(encrypted_data)[2:-1]
}
}
pub = rsa.lo
to_send = json.dumps(query)
to_send = to_send.encode()
return to_send
except Exception as ex:
print("Error in creating message")
print(ex)
except Exception as ex:
to_send = str(ex).encode()
return to_send
Но я получаю эту ошибку:
Error in creating message
'utf-8' codec can't decode byte 0xfc in position 5: invalid start byte
Exception in thread Thread-2:
Traceback (most recent call last):
File "C:\Users\vladi\AppData\Local\Programs\Python\Python37\lib\threading.py", line 926, in _bootstrap_inner
self.run()
File "C:\Users\vladi\AppData\Local\Programs\Python\Python37\lib\threading.py", line 870, in run
self._target(*self._args, **self._kwargs)
File "C:\Users\vladi\Documents\Programming\python\Server_Client\Client\client.py", line 28, in send
self.sock.send(str(len(data_to_send)).encode())
TypeError: object of type 'NoneType' has no len()```
Интересно, какого результата вы ожидаете, когда декодируете случайные байты в строку utf8? Base64, как упоминалось в ответе nneonneos, - правильный путь.
Декодирование строки байтов как utf-8 имеет смысл только в том случае, если вы знаете, что байты представляют действительные данные utf-8. utf-8 не будет декодировать произвольные строки байтов: существует определенный формат (когда байты >= 0x80, они интерпретируются как «начальные» или «продолжительные» байты и должны следовать определенным шаблонам; см. страницу Википедии для получения дополнительной информации. информация).
С другой стороны, шифрование данных (с использованием практически любого алгоритма шифрования) будет генерировать случайные строки байтов, которые почти наверняка не будут действительными utf-8.
Решение состоит в том, чтобы обрабатывать выходные данные процесса шифрования как строку байтов — не пытайтесь декодировать их в строку, так как это не будет иметь смысла как строка. Python обеспечивает различие между байтами и строкой именно для таких случаев: байты предназначены для двоичных данных (например, зашифрованных данных), строки — для текстовых данных.
Для вывода двоичных данных (в виде строк байтов) в JSON я предлагаю использовать кодировку, например Base64, чтобы кодировать байты в ASCII, а не пытаться использовать строку. Это будет более эффективно и намного проще в отладке.
если это кому-то когда-нибудь понадобится
import rsa
import base64
---------
pub, priv = rsa.newkeys(512)
---------
message_to_send = "Hello Vlad!"
b_message = message_to_send.encode()
encrypted = rsa.encrypt(b_message, pub)
encrypted_b64 = base64.b64encode(encrypted)
encrypted_b64_string = encrypted_b64.decode()
# -- sending via socket --
message_to_recieve = encrypted_b64_string
encrypted_b64 = message_to_recieve.encode()
encrypted = base64.b64decode(encrypted_b64)
b_final_message = rsa.decrypt(encrypted, priv)
final_message = b_final_message.decode()
-----------------------
print('message_to_send')
print(message_to_send)
print('b_message')
print(b_message)
print('encrypted')
print(encrypted)
print('encrypted_b64')
print(encrypted_b64)
print('encrypted_b64_string')
print(encrypted_b64_string)
print('message_to_recieve')
print(message_to_recieve)
print('encrypted_b64')
print(encrypted_b64)
print('encrypted')
print(encrypted)
print('b_final_message')
print(b_final_message)
print('final_message')
print(final_message)
---------------
message_to_send
Hello Vlad!
b_message
b'Hello Vlad!'
encrypted
b'5\x11\xeds\r\rF)&mt\x8bR\xc7\x9cf\x98/V#b[\x04\xe3\x90\x1f$R?=\xaa\xe0\x02\xba\xbeg\xec^F\xae+\x17\xab\xc1\xd1b[\xed\xce\xd8\x15\x18~99\x8a\xc3\xe0^2\x88Iy\xb5'
encrypted_b64
b'NRHtcw0NRikmbXSLUsecZpgvViNiWwTjkB8kUj89quACur5n7F5GrisXq8HRYlvtztgVGH45OYrD4F4yiEl5tQ=='
encrypted_b64_string
NRHtcw0NRikmbXSLUsecZpgvViNiWwTjkB8kUj89quACur5n7F5GrisXq8HRYlvtztgVGH45OYrD4F4yiEl5tQ==
message_to_recieve
NRHtcw0NRikmbXSLUsecZpgvViNiWwTjkB8kUj89quACur5n7F5GrisXq8HRYlvtztgVGH45OYrD4F4yiEl5tQ==
encrypted_b64
b'NRHtcw0NRikmbXSLUsecZpgvViNiWwTjkB8kUj89quACur5n7F5GrisXq8HRYlvtztgVGH45OYrD4F4yiEl5tQ=='
encrypted
b'5\x11\xeds\r\rF)&mt\x8bR\xc7\x9cf\x98/V#b[\x04\xe3\x90\x1f$R?=\xaa\xe0\x02\xba\xbeg\xec^F\xae+\x17\xab\xc1\xd1b[\xed\xce\xd8\x15\x18~99\x8a\xc3\xe0^2\x88Iy\xb5'
b_final_message
b'Hello Vlad!'
final_message
Hello Vlad!
Мужик, спасибо!. Я трачу на это много часов, и ваш ответ мне очень помог. Таааааааааааанс
на самом деле, это основная ошибка, и позиция неправильного байта меняется, когда я меняю кодек pubkey 'utf-8', не могу декодировать байт 0xfc в позиции 5: неверный стартовый байт