user783836
user783836

Reputation: 3529

pyaes and the relationship between byte and str in Python 3?

I'm trying to use pyaes (https://github.com/ricmoo/pyaes/blob/master/README.md) in Python 3 to encrypt and decrypt text using pyaes. When I encrypt text, I give pyaes a str value i.e.

plaintext = 'plain text'
key = os.urandom(16)
aes = pyaes.AESModeOfOperationCTR(key)
ciphertext = aes.encrypt(plaintext)

when I decrypt though, I get back a bytes type:

aes = pyaes.AESModeOfOperationCTR(key)
decrypted_plaintext = aes.decrypt(ciphertext)

Printing decrypted_plaintext produces the following output, which seems to contain the original text:

b'plain text'

But its not quite the same; one is a str the other is a bytes:

plaintext == decrypted_plaintext # False

I'm struggling to understand the relationship between bytes and whatever Python 3's internal representation of str is. How do I convert the bytes type into str to get my plaintext?

I have confirmed that running the examples on the pyaes readme page have the same problem. I'm guessing that is going to be something to do with encodings.

Upvotes: 2

Views: 1715

Answers (3)

Andy
Andy

Reputation: 41

for all others, this can help you: if decrypted.decode('utf-8') == plaintext:

    # A 256 bit (32 byte) key
key = b"This_key_for_demo_purposes_only!"

aes = pyaes.AESModeOfOperationCTR(key)
plaintext = "Text may be any length you wish, no padding is required"
ciphertext = aes.encrypt(plaintext)

# '''\xb6\x99\x10=\xa4\x96\x88\xd1\x89\x1co\xe6\x1d\xef;\x11\x03\xe3\xee
#    \xa9V?wY\xbfe\xcdO\xe3\xdf\x9dV\x19\xe5\x8dk\x9fh\xb87>\xdb\xa3\xd6
#    \x86\xf4\xbd\xb0\x97\xf1\t\x02\xe9 \xed'''
print (repr(ciphertext))

# The counter mode of operation maintains state, so decryption requires
# a new instance be created
aes = pyaes.AESModeOfOperationCTR(key)
decrypted = aes.decrypt(ciphertext)

print(type(decrypted))
print(type(plaintext))

# True
if decrypted.decode('utf-8') == plaintext:
    print(plaintext)
    print(True)
    print(decrypted.decode('utf-8'))


# '''WZ\x844\x02\xbfoY\x1f\x12\xa6\xce\x03\x82Ei)\xf6\x97mX\x86\xe3\x9d
#    _1\xdd\xbd\x87\xb5\xccEM_4\x01$\xa6\x81\x0b\xd5\x04\xd7Al\x07\xe5
#    \xb2\x0e\\\x0f\x00\x13,\x07'''
print (repr(ciphertext))

Upvotes: 0

Tryph
Tryph

Reputation: 6209

In Python 3 str type represents a string in unicode format. It is composed of relatively abstract codepoints, that is numbers coding characters. There are several ways to transform (encode) those codepoints to actual bytes which are known as "encodings". utf-8 and utf-16 are some encodings which allow to encode unicode characters.

Note that some encoding (as ASCII) does not allow to encode unicode characters.

When you encode a str string in Python, you obtain a list of bytes of type bytes. You can then decode this list of bytes to get a strstring.

The point to keep in mind is that you have to specify an encoding to encode a str string and you have to know the encoding of a bytesstring to be able to decode it. If you don't specify encoding, Python will try to encode and decode with its default encoding and you could obtain "random" results.

In you specific case, the difference is not visible because all the characters of your strings are ASCII chars and, fortunately, the 128 first codepoints of unicode match the ASCII table.

Try to introduce some 'exeotic' characters (like é, ç or Ë) in your string and you will see a difference.


Now, pyaes does not encrypt/decrypt unicode codepoints but bytes. So you have to encode the strings you encrypt and you have to know the used encoding to decode the decrypted strings.


More information in the Python doc:

Upvotes: 1

cxw
cxw

Reputation: 17051

decrypted_plaintext.decode() will give you a str, which will most likely be what you want. A bytes object is a raw string of bytes in an unspecified encoding. To convert that to a str, you have to tell Python to decode it using decode(). decode() defaults to UTF-8, but you can tell it which encoding to use.

I just took a glance at the source and I see nothing encoding-specific, so the encoding of the decrypted string should match that of the encrypted string.

Upvotes: 0

Related Questions