0
#encrypting an image using AES
import binascii
from Crypto.Cipher import AES


def pad(s):
  return s + b"\0" * (AES.block_size - len(s) % AES.block_size)

filename = 'path to input_image.jpg'
with open(filename, 'rb') as f:
  content = f.read()

#converting the jpg to hex, trimming whitespaces and padding.
content = binascii.hexlify(content)
binascii.a2b_hex(content.replace(' ', ''))
content = pad(content)

#16 byte key and IV
#thank you stackoverflow.com
obj = AES.new('This is a key123', AES.MODE_CBC, 'This is an IV456')
ciphertext = obj.encrypt(content)

#is it right to try and convert the garbled text to hex?
ciphertext = binascii.hexlify(ciphertext)
print ciphertext

#decryption

obj2 = AES.new('This is a key123', AES.MODE_CBC, 'This is an IV456')
plaintext = obj2.decrypt(ciphertext)
#content =  content.encode('utf-8')
print plaintext
#the plaintext here matches the original hex input file as it should


with open('path to - AESimageDecrypted.txt', 'wb') as g:
   g.write(plaintext)

My question is two fold, 1) how would i go about converting the encrypted file (which is garbled before hexlify) which is basically a text file of hex strings, back into an image? i'd like the output to be viewable as a jpg on any viewer.

I've tried a few things out , came across Pillow, except i can't seem to grasp if it can do what i want.

Any help would be appreciated thanks.

PS: i want to try this with other ciphers too. so i think it'd be helpful if anyone can help clear out if this understanding is right:

jpg -> convert to binary/hex -> encrypt -> garbled output -> convert to bin/hex -> convert to jpg

2) is the above possible? and should they be converted to hex or bin?

baconSoda
  • 503
  • 2
  • 5
  • 15
  • To revert hexlify + encrypt, apply decrypt + unhexlify? – zvone Oct 08 '16 at 19:58
  • @zvone is there a way to hexlify + encrypt -> convert to jpg ? To be clearer, i'd like to know if there's a way to take the garbled ciphertext, and convert that to an image ? – baconSoda Oct 08 '16 at 20:04
  • Of course there is a way, but I still do not understand what the problem is. First, why are you converting the jpg to hex at all? Second, it looks like you have everything except converting hex to the original. You have that here: http://stackoverflow.com/q/9641440/389289 – zvone Oct 08 '16 at 20:17
  • @zvone the goal that im trying to achieve is that i have a plain photo that i want to encrypt with AES. i want the resultant ciphertext to be able to open like a photo as well. This cipher photo (for want of a better term) should later be able to decrypted to th original image. I think i was converting to hex in an attempt to figure this out for myself before posting here... i got stumped with the cipher text. it's basically unreadable symbols. so how would you convert such a txt file to a jpg (or any photo format) WITHOUT decryption ( i expect the image to just be noise) – baconSoda Oct 08 '16 at 20:26
  • I guess if you just do `ciphertext = obj.encrypt(content)` and `content = obj2.decrypt(ciphertext)` without any padding, encoding, hexlifying etc, that should work. – zvone Oct 08 '16 at 20:29
  • @zvone thanks, but that's just encryption and decryption... I want to know if there's a way to see the cipher text as an image. Appreciate the help nonetheless – baconSoda Oct 08 '16 at 20:30
  • What would you expect to see if you showed the encrypted contents as an image? It could be made into something similar to white noise. Is that what you want? – zvone Oct 08 '16 at 21:23
  • yes absolutely. that would be perfect. i'd like to try the same with RC4, DES etc later, but the exact process is confusing. i also plan on using stepic to see if i can try and encode text into images – baconSoda Oct 08 '16 at 21:25
  • What is a "file of hex"? Perhaps ypu mean binary? What is in a file is all about how you look at it, Binary, characters, hex, image, etc. – zaph Oct 08 '16 at 21:47

1 Answers1

4

The question here is how to display encrypted image as an image without decrypting it.

The encrypted contents are not an image and cannot be unambiguously represented as an image. The best that can be done is to treat it as a bitmap, i.e. each binary value represents the intensity of some color at some coordinate.

It seems logical to treat the data as 3 bytes per pixel: RGB RGB RGB...

Images are 2D and encrypted data is just a list of bytes. Again, several options are valid. Let's say it is a square image (NxN pixels).

To create the image, I would use PIL / Pillow:

from PIL import Image

# calculate sizes
num_bytes = len(cyphertext)
num_pixels = int((num_bytes+2)/3)                     # 3 bytes per pixel
W = H = int(math.ceil(num_pixels ** 0.5))             # W=H, such that everything fits in

# fill the image with zeros, because probably len(imagedata) < needed W*H*3
imagedata = cyphertext + '\0' * (W*H*3 - len(cyphertext))

image = Image.fromstring('RGB', (W, H), imagedata)         # create image
image.save('C:\\Temp\\image.bmp')                          # save to a file

BTW, this can be done with absolutely any string of bytes, not just encrypted images.

zvone
  • 18,045
  • 3
  • 49
  • 77
  • this helped solve the issue. I checked out the differences between DES and AES. I want to check if it's the same with say a caeser cipher. Whether the bitmaps betray any sort of data. Thanks a ton zvone. – baconSoda Oct 09 '16 at 00:01