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.
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.
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()