2

I'm encoding a message with rsa.encrypt but then I cannot convert the encrypted data to a str with .decode(). That's a bit strange because the encrypted data is a bytes string and there shouldn't be any problem converting that to a str.

data = [self.id, data, self.my_pubkey] # actually don't care about type of components, they are correct

My code:

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

But, I'm getting this error:

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()```
2
  • actually, this is the main error, and the position of the wrong byte changing while I'm changing pubkey 'utf-8' codec can't decode byte 0xfc in position 5: invalid start byte Commented Dec 10, 2020 at 8:01
  • I wonder what kind of result you're expecting when you decode a random bytes to a utf8 string? Base64, as mentioned in nneonneos answer, is the right way. Commented Dec 10, 2020 at 9:19

2 Answers 2

4

if someone will need it someday

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!
Sign up to request clarification or add additional context in comments.

1 Comment

Man, thank you!. I spend many hours on that and your answer helped me a lot. Thaaaaaaaaanks
3

Decoding a byte string as utf-8 only makes sense if you know the bytes represent valid utf-8 data. utf-8 will not decode arbitrary byte strings: there's a specific format (when bytes are >= 0x80, they are interpreted as either "start" or "continuation" bytes and must follow certain patterns; see the Wikipedia page for more information).

On the other hand, encrypting data (using almost any encryption algorithm) will generate random-looking byte strings that almost certainly will not be valid utf-8.

The solution is to treat the output of the encryption process as a byte string - do not attempt to decode it to a string, as it will not make sense as a string. Python provides the bytes/str distinction precisely for this kind of case: bytes are for binary data (e.g. encrypted data), strings are for textual data.

For dumping binary data (as byte strings) into JSON, I suggest using an encoding like Base64 to encode the bytes into ASCII, rather than trying to use a string. This will be more efficient and much easier to debug.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.