0

so i have function for encryption and decryption using AES CTR. i was using python 3.x and the idea for this aes ctr from tweaksp

when i try to decrypt to get the plaintext, i got error message:

'bytes' object has no attribute 'encode'

after i check another stackoverflow, i found if .encode('hex') not works on python 3.x base this here's my code for encrypt:

key_bytes = 16
def encrypt(key, pt):
    plaintext = read_file(pt)
    if isinstance(plaintext, str):
        pt= plaintext.encode("utf-8")

    if len(key) <= key_bytes:
        for x in range(len(key),key_bytes):
            key = key + "0"

    assert len(key) == key_bytes
    
    # Choose a random, 16-byte IV.
    iv = Random.new().read(AES.block_size)

    # Convert the IV to a Python integer.
    iv_int = int(binascii.hexlify(iv), 16)

    # Create a new Counter object with IV = iv_int.
    ctr = Counter.new(AES.block_size * 8, initial_value=iv_int)

    # Create AES-CTR cipher.
    aes = AES.new(key.encode('utf8'), AES.MODE_CTR, counter=ctr)

    # Encrypt and return IV and ciphertext.
    ciphertext = aes.encrypt(pt)
    return (iv, ciphertext)

what i input for decrypt

key : maru000000000000

iv : b'he\xf5\xba\x9bf\xf4\xacfA\xa6\xc7\xce\xd0\x90j'

ciphertext : 01101000011001011111010110111010100110110110011011110100101011000110011001000001101001101100011111001110110100001001000001101010

and my decrypt code:

def decrypt(key, iv, ciphertext):
    assert len(key) == key_bytes
    print(type(iv))
    # Initialize counter for decryption. iv should be the same as the output of
    # encrypt().
    iv_int = int(iv.encode('hex'), 16) 
    ctr = Counter.new(AES.block_size * 8, initial_value=iv_int)

    # Create AES-CTR cipher.
    aes = AES.new(key, AES.MODE_CTR, counter=ctr)

    # Decrypt and return the plaintext.
    plaintext = aes.decrypt(ciphertext)
    return plaintext

error

1 Answers1

0

OK, I found the problem. I commented the offending code and replaced it with iv_int = int(binascii.hexlify(iv), 16) This is the updated code that works:

from Crypto import Random
from Crypto.Cipher import AES
from Crypto.Util import Counter

import binascii

key_bytes = 16
def encrypt(key, plaintext):
    if isinstance(plaintext, str):
        pt= plaintext.encode("utf-8")

    if len(key) <= key_bytes:
        for x in range(len(key),key_bytes):
            key = key + "0"

    assert len(key) == key_bytes
    
    # Choose a random, 16-byte IV.
    iv = Random.new().read(AES.block_size)

    # Convert the IV to a Python integer.
    iv_int = int(binascii.hexlify(iv), 16)

    # Create a new Counter object with IV = iv_int.
    ctr = Counter.new(AES.block_size * 8, initial_value=iv_int)

    # Create AES-CTR cipher.
    aes = AES.new(key.encode('utf8'), AES.MODE_CTR, counter=ctr)

    # Encrypt and return IV and ciphertext.
    ciphertext = aes.encrypt(pt)
    return (iv, ciphertext)

def decrypt(key, iv, ciphertext):
    assert len(key) == key_bytes
    # Initialize counter for decryption. iv should be the same as the output of
    # encrypt().
    #iv_int = int(iv.encode('hex'), 16) 
    iv_int = int(binascii.hexlify(iv), 16)
    ctr = Counter.new(AES.block_size * 8, initial_value=iv_int)

    # Create AES-CTR cipher.
    aes = AES.new(key, AES.MODE_CTR, counter=ctr)

    # Decrypt and return the plaintext.
    plaintext = aes.decrypt(ciphertext)
    return plaintext

plaintext = 'This is just a test'
key = 'maru000000000000'
iv, ciphertext = encrypt(key, plaintext)
print(ciphertext)
decrypted_text = decrypt(key, iv, ciphertext)
print(decrypted_text)

The following gives the same result as int(binascii.hexlify(iv), 16)

iv_int = int.from_bytes(iv, byteorder='little', signed=False)
Tarik
  • 10,810
  • 2
  • 26
  • 40
  • okay it's not error again. but why the result from plaintext is bytes? not the plaintext – PyhonLovers Dec 01 '22 at 16:12
  • aes.decrypt returns a byte array. You can decode it to utf-8 string. – Tarik Dec 02 '22 at 17:05
  • when i tried to decode, i got error message : 'utf-8' codec can't decode byte 0xac in position 0: invalid start byte – PyhonLovers Dec 03 '22 at 07:59
  • I used `decrypted_text.decode(encoding='utf-8')` and it worked perfectly. Your readfile function might be returning data that ends up not being properly encoded as UTF-8. I would also not call readfile from the encrypting function to separate responsibilities. encrypt should just take some plain text in UTF-8 and encrypt it. You can test that function along with the decrypt function independently. If all works ok, you figure out what's wrong with the read function or whatever data you are throwing at you encrypt function. Your question has been answered. For courtesy, mark it as answered. – Tarik Dec 04 '22 at 05:02