2

I am trying to test create a simple cipher that xor key with a bitmap image.

import os, io, hashlib
from PIL import Image
from array import array
from itertools import cycle

key = "aaaabbbb"

def generate_keys(key):
    round_keys = hashlib.md5(key).digest()
    return bytearray(round_keys)

def readimage(path):
    with open(path, "rb") as f:
            return bytearray(f.read())

def generate_output_image(input_image, filename_out):
    output_image = Image.open(io.BytesIO(input_image))
    output_image.save(filename_out)

def xor(x,y):
    return [ a ^ b for a,b in zip(x,cycle(y))]

round_keys = generate_keys(key)
input_image = readimage("lena512.bmp")
encrypted_image = xor(input_image, round_keys)
generate_output_image(encrypted_image, "lena_encrypted.bmp")

input_image = readimage("lena_encrypted.bmp");
decrypted_image = xor(input_image, round_keys)
generate_output_image(decrypted_image, "lena_decrypted.bmp")

But I'm getting the following error when I run the script:

Traceback (most recent call last):
    File "test.py", line 26, in <module>
        generate_output_image(encrypted_image, "lena_encrypted.bmp")
    File "test.py", line 17, in generate_output_image
        output_image = Image.open(io.BytesIO(input_image))
TypeError: 'list' does not have the buffer interface

How do I convert the byte array back into bitmap image? Any help would be appreciated thanks.

3
  • Your xor function returns a list, so you can't pass encrypted_image and decrypted_image as an argument to io.BytesIO(). Maybe changing the xor function to return bytearray([ a ^ b for a,b in zip(x,cycle(y))]) could help. Commented Dec 7, 2018 at 16:29
  • Thanks myrmica. Your suggestion helped when I'm converting the decrypted bytearray into bitmap image. However, I could not convert encrypted bytearray to bitmap image. I was hoping to get an image of white noise and will be able to decrypt the white noise image back to the original bitmap. Any idea how to do that? Commented Dec 7, 2018 at 17:26
  • BMP files have a header with information that you must not modify with your cipher. There should be something like return x[:54] + bytearray([a^b for a, b in zip(x[54:], cycle(y))]) in the xor function. The actual offset may differ though, as there are different versions of BMP. Commented Dec 7, 2018 at 20:46

2 Answers 2

2

I looked a bit more into how to retrieve/update the image data more elegantly with the tools included in PIL/Pillow, and made this simple working example:

from PIL import BmpImagePlugin
import hashlib
from itertools import cycle

keys = hashlib.md5(b"aaaabbbb").digest()

input_image = BmpImagePlugin.BmpImageFile("img/tea.bmp")

# extract pure image data as bytes
image_data = input_image.tobytes()

# encrypt
image_data = bytes(a^b for a, b in zip(image_data, cycle(keys)))

# create new image, update with encrypted data and save
output_image = input_image.copy()
output_image.frombytes(image_data)
output_image.save("img/tea-encrypted.bmp")

This way, you don't have to worry about the BMP header size.

(links: original and encrypted image)

Sign up to request clarification or add additional context in comments.

Comments

1

Updated script thats convert plain image to cipher image and back to plain image.

import os, io, hashlib, math, binascii
from PIL import Image
from array import array
from itertools import cycle

user_key = "aaaabbbb"
test_image = "lena512.bmp"

def generate_keys(key):
    round_keys = hashlib.md5(key).digest()
    return bytearray(round_keys)

def readimage(path):
    with open(path, "rb") as f:
            return bytearray(f.read())

def generate_output_image(input_image):
    output_image = Image.open(io.BytesIO(input_image))
    output_image.save(test_image)

def xor(x,y):
    return x[:54] + bytearray([a^b for a, b in zip(x[54:], cycle(y))])

round_keys = generate_keys(user_key)
input_image = readimage(test_image)
encrypted_image = xor(input_image, round_keys)
generate_output_image(encrypted_image)

input_image = readimage(test_image);
decrypted_image = xor(input_image, round_keys)
generate_output_image(decrypted_image)

Thanks myrmica for your help

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.