I have a web based application that requires images to be encrypted before they are sent to server, and decrypted after loaded into the browser from the server, when the correct key was given by a user.
[Edit: The goal is that the original image and the key never leaves the user's computer so that he/she is not required to trust the server.]
My first approach was to encrypt the image pixels using AES and leave the image headers untouched. I had to save the encrypted image in lossless format such as png. Lossy format such as jpg would alter the AES encrypted bits and make them impossible to be decrypted.
Now the encrypted images can be loaded into the browser, with a expected completely scrambled look. Here I have JavaScript code to read in the image data as RGB pixels using Image.canvas.getContext("2d").getImageData()
, get the key form the user, decrypt the pixels using AES, redraw the canvas and show the decrypted image to the user.
This approach works but suffers two major problems.
The first problem is that saving the completely scrambled image in lossless format takes a lot of bytes, close to 3 bytes per pixel.
The second problem is that decrypting large images in the browser takes a long time.
This invokes the second approach, which is to encrypt the image headers instead of the actual pixels. But I haven't found any way to read in the image headers in JavaScript in order to decrypt them. The Canvas gives only the already decompressed pixel data. In fact, the browser shows the image with altered header as invalid.
Any suggestions for improving the first approach or making the second approach possible, or providing other approaches are much appreciated.
Sorry for the long post.