Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / security

Simple Image Drag/Zoom Tool using Memory Streams

2.50/5 (5 votes)
15 Apr 2020CPOL4 min read 12.4K   220  
Working with decrypted data only in memory leaving no traces in hard-drive
This simple application will demonstrate how to load the image from hard drive into memory, then decrypt it as a memory stream, then display it without the need to write a physical file on the hard drive, keeping your image much more safe in the memory and preventing image recovery by ordinary tools from hard drive. In this tip, some concepts are demonstrated including how to load images in memory as a memory stream, how to drag and move object on a form and how to zoom-in / zoom-out for images.

Introduction

In many cases, we would like to store encrypted image files, yet while loading the file, we might have to decrypt by writing a new file to the hard drive, and this is not really secure, and the newly written file might remain undeleted on the hard drive in a temp folder, or might be recovered using some undelete tools, rendering the image insecure and may be viewed by others. This simple application will demonstrate how to load the image from hard drive into memory, then decrypt it as a memory stream, then display it without the need to write a physical file on the hard drive, keeping your image much more safe in the memory and preventing image recovery by ordinary tools from hard drive. It also guarantees that by closing the application, all data in memory is lost, while what remains is only the original encrypted file on the hardrive that is not viewable by any image tools.

During this tip, I shall demonstrate quickly and easily the following concepts:

  1. Loading Images in Memory as a memory stream
  2. How to drag and move object on a form (in this article, a Picturebox)
  3. Zoom-in / Zoom-out for images (using Picturebox)

Important Note: The aim in this article is not the encryption itself, so I will not be using real solid encryption, yet I will only use XOR to demonstrate the concept. In the real world, you are required to replace XOR with actual solid encryption (i.e., AES or so). Due to this, I will not also be conducting encryption key verification, I will only use a constant key for demonstration purposes.

**I have not added any error handling in the code, normally you would want to use Try, catch, & Finally to handle errors.

Background

Well, I wrote this code because I wanted to secure my own images without zipping them with password, and also to guarantee that a decrypted image is viewable and not recoverable once viewing is complete, so I won't rely on temp file at all to decrypt and view image, so I had to develop my own solution.

Using the Code

1. Loading Image to Memory

The core idea is very simple and uses direct .NET features allowing loading a file into memory as a byte array, the ability of .NET to construct a Memory Stream from byte arrays, then we can construct an image directly from Memory stream and display it.

So note in this line, we load the full encrypted file into memory:

C#
byte[] ImageBytes = null;
ImageBytes = File.ReadAllBytes(aFile);

The next step is to start decrypting the data loaded into memory directly into a byte array.

Note: Here only XOR is used, but this is not solid encryption, you should use AES instead, so this is for demonstration only.

C#
byte key = 215;

for (int j = 0; j < ImageBytes.Length; j++)
                {
                    //XOR represents a mathematical reversible transformation 
                    //in a very simple form. 
                    //Note: You better use here whatever encryption algorithm you wish, 
                    //this is for demonstration only.
                    ImageBytes[j] ^= key;
                }

The final step is to use the new byte array representing an image and convert it to actual image, so we can view it in picture box, the following simple function does this part:

C#
public Image byteArrayToImage(byte[] byteArrayIn)
        {
            MemoryStream ms = new MemoryStream(byteArrayIn);
            Image returnImage = Image.FromStream(ms);
            //Clone() is used so when the stream is closed,
            //we retain a new memory copy created by Clone.
            return returnImage.Clone();
        }

As the return is an Image, you can view the image very simply by assigning it to a picturebox:

C#
pictureBox1.Image = byteArrayToImage(ImageBytes);

2. Dragging Object Across Form

Well, the concept is simple and is only about using suitable mouse events in the right time, it is simply in the three following steps:

You will need to retain drag flag and position info in globals to be used across multiple events:

C#
int DragFlag = 0;
int CurX = 0;
int CurY = 0;
  1. In MouseDown event, you need to indicate drag is being done by DragFlag, and capture current coordinates:
    C#
    private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
            {
                DragFlag = 1;
                CurX = e.X;
                CurY = e.Y;
            }
  2. During mouse movement, you need now to move your object accordingly as long as mouse is down as indicated by the DragFlag:
    C#
    private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
            {
                if (DragFlag == 1)
                {
                    pictureBox1.Left += (e.X - CurX);
                    pictureBox1.Top += (e.Y - CurY);
                }
            }
  3. The final step is when mouse is released, you have to clear the flag:
    C#
    private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
            {
                DragFlag = 0;
            }

3. Zooming Image

Zooming and image in .NET is very easy due to the size mode named zoom, the trick is to set this mode for a PictureBox just before you resize as follows:

C#
pictureBox1.SizeMode = PictureBoxSizeMode.Zoom;

Now the only thing required is to resize the pictureBox for zoom-in and zoom-out cases as follows:

Zoom in:

C#
private void btnZoomIn_Click(object sender, EventArgs e)
       {
           float zoom = 0.1f;
           pictureBox1.Height +=(int) (zoom * pictureBox1.Height);
           pictureBox1.Width += (int)(zoom * pictureBox1.Width);
       }

and Zoom-out:

C#
private void btnZoomOut_Click(object sender, EventArgs e)
        {
            float zoom = 0.1f;
            pictureBox1.Height -= (int)(zoom * pictureBox1.Height);
            pictureBox1.Width -= (int)(zoom * pictureBox1.Width);
        }

Quick UI Guide

  1. Loading normal JPG
    • Make sure "Encrypted Image" is Unchecked
    • Click "Load" and select the JPG as needed
  2. Encrypting an Image
    • Make sure an un-encrypted image is already loaded
    • Make sure "Encrypted Image" is now checked
    • Click "Save" and set target file name
  3. Loading Encrypted Image
    • Make sure "Encrypted Image" is checked
    • Click "Load" and select the JPG as needed
  4. View multiple files in slide mode
    • Click on "Slide Files" and select multiple JPG files
    • If files are encrypted, make sure you selected "Encrypted Image" before selecting slide files
    • Use the arrows to navigate forward and backward through images
  5. Encrypting multiple images in batch mode
    • Click on "Batch"
    • Select multiple JPG files
    • All images will be encrypted and saved in the same source folder and ".cry" is appended to the original file name
  6. Additional features
    • You may also use "+" & "-" to zoom in and out at any time while an image is displayed
    • You may also drag and open image around the form freely

History

  • 16th April, 2020: Initial version

License

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