Search code examples
pythonencryptioncryptographyaes

AES - how do I convert a byte-string string to a byte byte-string?


I am trying my hand at AES. I am trying to pass an encrypted message entirely in a procedure:

    import hashlib
    import os
    import base64

    from Crypto.Cipher import AES

    IV_SIZE = 16    # 128 bit, fixed for the AES algorithm
    KEY_SIZE = 32   # 256 bit meaning AES-256, can also be 128 or 192 bits
    SALT_SIZE = 16  # This size is arbitrary

    cleartext = b'Lorem ipsum'
    password = b'highly secure encryption password'
    salt = os.urandom(SALT_SIZE)
    derived = hashlib.pbkdf2_hmac('sha256', password, salt, 100000,
                              dklen=IV_SIZE + KEY_SIZE)
    iv = derived[0:IV_SIZE]
    key = derived[IV_SIZE:]

    encrypted = salt + AES.new(key, AES.MODE_CFB, iv).encrypt(cleartext)

    print(encrypted)
    ############################################
    #This is where the examples are being tried
    encrypted = str(encrypted).encode('unicode-escape')
    ###########################################

    encryptedString = base64.encodebytes(encrypted)

    print(encryptedString) 

    encrypted = base64.decodebytes(encryptedString) # <- get the bytes back

    salt = encrypted[0:SALT_SIZE]
    derived = hashlib.pbkdf2_hmac('sha256', password, salt, 100000,
                              dklen=IV_SIZE + KEY_SIZE)
    iv = derived[0:IV_SIZE]
    key = derived[IV_SIZE:]
    cleartext = AES.new(key, AES.MODE_CFB, iv).decrypt(encrypted[SALT_SIZE:])

    print(cleartext)

I get the following error: expected bytes-like object, not str

Basically I'm trying to convert a string(byte string) to a byte(byte string). Normally I would pass the string with a b in front of it, like: b'?j\xf5\xd3\x8bP\xe5\xd5\xcd\xa2]\xa7\xf7\xc7\x9cO\x92\x0f\xdb}\xf5N\xb94J\xc7\x13'

But in this case the encrypted message will be received as a string and must be converted to bytes.

I have tried:

encrypted = str(encrypted).encode('utf-8')

encrypted = bytes(str(encrypted), 'utf-8')

encrypted = str(encrypted).encode('unicode-escape')

These examples do not yield errors, but the script is encrypting them again instead of decrypting.


Solution

  • Using snakecharmerb's suggested answer:

        import ast
        import hashlib
        import os
        import base64
    
        from Crypto.Cipher import AES
    
        IV_SIZE = 16    # 128 bit, fixed for the AES algorithm
        KEY_SIZE = 32   # 256 bit meaning AES-256, can also be 128 or 192 bits
        SALT_SIZE = 16  # This size is arbitrary
    
        cleartext = b'Lorem ipsum'
        password = input('Password: ')
        password = bytes(password, 'utf-8')
        salt = os.urandom(SALT_SIZE)
        derived = hashlib.pbkdf2_hmac('sha256', password, salt, 100000,
                                      dklen=IV_SIZE + KEY_SIZE)
        iv = derived[0:IV_SIZE]
        key = derived[IV_SIZE:]
    
        encrypted = salt + AES.new(key, AES.MODE_CFB, iv).encrypt(cleartext)
    
        print(encrypted)
    
        ############################################
        encrypted = ast.literal_eval(str(encrypted))
        ###########################################
    
        encryptedString = base64.encodebytes(encrypted)
    
        print(encryptedString) 
    
        encrypted = base64.decodebytes(encryptedString) # <- get the bytes back
    
        salt = encrypted[0:SALT_SIZE]
        derived = hashlib.pbkdf2_hmac('sha256', password, salt, 100000,
                                      dklen=IV_SIZE + KEY_SIZE)
        iv = derived[0:IV_SIZE]
        key = derived[IV_SIZE:]
        cleartext = AES.new(key, AES.MODE_CFB, iv).decrypt(encrypted[SALT_SIZE:])
    
        print(cleartext)