Click here to Skip to main content
15,888,041 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I am using the following code to encode and decode an image using AES in ECB mode. Once the image is decoded it is supposed to look exactly the same as the original. However, there is a problem with the operation because the images are not the same (though it is visually not possible to see a difference). The original image is 19kb but the decoded image is 397 kb. Any insight on what I need to change to make the images the same size will be highly appreciated.

Python
from PIL import Image, ImageFile
    from Cryptodome.Cipher import AES
    from io import BytesIO
    
    filename = "jessica.bmp"
    filename_out = "1_enc_img"
    
    key = "aaaabbbbccccdddd"
    ImageFile.LOAD_TRUNCATED_IMAGES = True
    
    def pad(data):
        bytearray_data = bytearray()
        l = 0
        for i in range(1, len(data), 1):
            bytearray_data += bytearray(data[l: i] + b"\x00" * (16 - len(data[l: i]) % 16))
            l = i
        return bytearray_data
    
    def process_image(filename):
        with open(filename, 'rb') as f:
            data = f.read()
        img_bytes = aes_ecb_encrypt(key, pad(data))
        
        f = open(filename_out, 'wb')
        f.write(img_bytes)
    
    def aes_ecb_encrypt(key, data, mode=AES.MODE_ECB):
        aes = AES.new(key.encode("utf8"), mode)
        new_data = aes.encrypt(data)
        return new_data
    
    def create_dictionary():
        dictionary = bytearray()
        for i in range(256):
            dictionary += bytearray(i.to_bytes(16, byteorder='little'))
        
        return dictionary
    
    def encrypt_dict(dictionary):
        return aes_ecb_encrypt(key, dictionary)
    
    def decode_image():
        with open('./dict', 'rb') as f:
            dictionary = f.read()
        im = open('./1_enc_img', 'rb')
        data2 = im.read()
        dict = {}
        c = 0
        l = 0
        dict_file = open('./dict.txt', 'a')
        for i in range(16, len(dictionary) + 1, 16):
            temp_dict = {(dictionary[l: i]): c.to_bytes(1, byteorder='little')}
            dict.update(temp_dict)
            
            dict_file.write("{} - {}\n".format(temp_dict, c))
            c += 1
            l = i
        c = 0
        l = 0
        result = bytearray()
        for i in range(16, len(data2), 16):
            
            result += dict[data2[l: i]]
            c += 1
            l = i
        stream = BytesIO(result)
        image = Image.open(stream).convert("RGBA")
        stream.close()
        picture = image.save("{}.bmp".format("decoded_image"))
    
    
    def main():
        f = open('./dict', 'wb')
        f.write(encrypt_dict(create_dictionary()))
        f.close()
        process_image(filename)
        decode_image()
    
    main()


What I have tried:

I am using the following code to encode and decode an image using AES in ECB mode. Once the image is decoded it is supposed to look exactly the same as the original. However, there is a problem with the operation because the images are not the same (though it is visually not possible to see a difference). The original image is 19kb but the decoded image is 397 kb. Any insight on what I need to change to make the images the same size will be highly appreciated.

Python
from PIL import Image, ImageFile
    from Cryptodome.Cipher import AES
    from io import BytesIO
    
    filename = "jessica.bmp"
    filename_out = "1_enc_img"
    
    key = "aaaabbbbccccdddd"
    ImageFile.LOAD_TRUNCATED_IMAGES = True
    
    def pad(data):
        bytearray_data = bytearray()
        l = 0
        for i in range(1, len(data), 1):
            bytearray_data += bytearray(data[l: i] + b"\x00" * (16 - len(data[l: i]) % 16))
            l = i
        return bytearray_data
    
    def process_image(filename):
        with open(filename, 'rb') as f:
            data = f.read()
        img_bytes = aes_ecb_encrypt(key, pad(data))
        
        f = open(filename_out, 'wb')
        f.write(img_bytes)
    
    def aes_ecb_encrypt(key, data, mode=AES.MODE_ECB):
        aes = AES.new(key.encode("utf8"), mode)
        new_data = aes.encrypt(data)
        return new_data
    
    def create_dictionary():
        dictionary = bytearray()
        for i in range(256):
            dictionary += bytearray(i.to_bytes(16, byteorder='little'))
        
        return dictionary
    
    def encrypt_dict(dictionary):
        return aes_ecb_encrypt(key, dictionary)
    
    def decode_image():
        with open('./dict', 'rb') as f:
            dictionary = f.read()
        im = open('./1_enc_img', 'rb')
        data2 = im.read()
        dict = {}
        c = 0
        l = 0
        dict_file = open('./dict.txt', 'a')
        for i in range(16, len(dictionary) + 1, 16):
            temp_dict = {(dictionary[l: i]): c.to_bytes(1, byteorder='little')}
            dict.update(temp_dict)
            
            dict_file.write("{} - {}\n".format(temp_dict, c))
            c += 1
            l = i
        c = 0
        l = 0
        result = bytearray()
        for i in range(16, len(data2), 16):
            
            result += dict[data2[l: i]]
            c += 1
            l = i
        stream = BytesIO(result)
        image = Image.open(stream).convert("RGBA")
        stream.close()
        picture = image.save("{}.bmp".format("decoded_image"))
    
    
    def main():
        f = open('./dict', 'wb')
        f.write(encrypt_dict(create_dictionary()))
        f.close()
        process_image(filename)
        decode_image()
    
    main()
Posted
Updated 7-Oct-22 1:51am
v2
Comments
Richard MacCutchan 7-Oct-22 8:00am    
Maybe adding all those extra bytes to the image is affecting it.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900