📜 ⬆️ ⬇️

Visual cryptography for color images

Recently I came across Habré for a couple of posts about hiding data in BMP files ( one and two ) and decided to share my experience in this field. This time we will hide the color image, and we will use three more images as containers.


A few words about BMP


The BMP file consists of a header - a structure of several tens of bytes containing the main image parameters (dimensions, color depth, etc.), a palette - an array describing the colors used in the image, and a data area containing a sequence of image pixel codes . The palette is not obligatory - in most BMP files there is no palette, and the data area contains a description of all the color components of each pixel of the image in the RGB format (that is, the quantitative values ​​of red, green, and blue).

Method Description


As input images, 24-bit bitmap images are used, in which each color has 8 bits of information. We will hide the data using the LSB method.
The essence of the algorithm is that the secret image is divided into three color primitives (that is, shades of red, green and blue), and then each primitive is written to the low-order bits of one of the image containers. Thus, after encryption, each container will contain one color component of the secret image.
')

Image encryption


To determine which of the images to hide the R-component, which one - G, and which one - B, before starting the algorithm, the quantitative value of each of the three shades in each image container is determined. Next, the containers are selected in such a way that the difference in the colors of the container and the color primitive of the secret image is minimal.
Then, from each color primitive, two high-order bits are taken and written to the low-order bits of the corresponding color in the corresponding container. The two lower bits in the two remaining colors are reset. The operation is repeated for each pixel.

The code of the function that writes the color primitive to the container
private Color CombineColorsRGB(Color secretColor, Color containerColor, HidingColor hidingColor) { byte r1 = secretColor.R; byte g1 = secretColor.G; byte b1 = secretColor.B; byte r2 = containerColor.R; byte g2 = containerColor.G; byte b2 = containerColor.B; int secretBits = m_secretBits; int originalBits = 8 - m_secretBits; switch (hidingColor) { case HidingColor.R: r1 = (byte)(r1 >> originalBits); r2 = (byte)((r2 >> secretBits) << secretBits); r2 = (byte)(r1 | r2); g2 = (byte)((g2 >> secretBits) << secretBits); b2 = (byte)((b2 >> secretBits) << secretBits); break; case HidingColor.G: g1 = (byte)(g1 >> originalBits); g2 = (byte)((g2 >> secretBits) << secretBits); g2 = (byte)(g1 | g2); r2 = (byte)((r2 >> secretBits) << secretBits); b2 = (byte)((b2 >> secretBits) << secretBits); break; case HidingColor.B: b1 = (byte)(b1 >> originalBits); b2 = (byte)((b2 >> secretBits) << secretBits); b2 = (byte)(b1 | b2); r2 = (byte)((r2 >> secretBits) << secretBits); g2 = (byte)((g2 >> secretBits) << secretBits); break; } Color col = Color.FromArgb(r2, g2, b2); return col; } 

This function is performed for each color of each pixel of the secret image.
In our case, m_secretBits = 2.

Secret Image:


A set of source images for encryption:






The same images, but already with a secret image encrypted in them:






As seen in the images, visually distortions are not noticeable. I apologize that the images are small - regretted traffic. On large images, distortions are also not noticeable - believe me.

Image Recovery


The next step is to restore the hidden image. To do this, take the first pixel from each image-container. We make the two low-order bits of each color in these pixels with the high-order bits and add the corresponding color components (since the low-order bits of an unencrypted color were zeroed during encryption, then only one color component in each container will have a non-zero value). Thus, we will restore the color of the corresponding pixel of the secret image (with some error). Then repeat this operation for all pixels and get the recovered secret image.

The code of the function that restores the secret image from the containers
 private Color GetSecretColorRGB(Color color1, Color color2, Color color3) { byte r1 = color1.R; byte g1 = color1.G; byte b1 = color1.B; byte r2 = color2.R; byte g2 = color2.G; byte b2 = color2.B; byte r3 = color3.R; byte g3 = color3.G; byte b3 = color3.B; int secretBitsDigit = (int)(Math.Pow(2.0, (double)m_secretBits)) - 1; int originalBits = 8 - m_secretBits; byte r = (byte)(((r1 & secretBitsDigit) << originalBits) + ((r2 & secretBitsDigit) << originalBits) + ((r3 & secretBitsDigit) << originalBits)); byte g = (byte)(((g1 & secretBitsDigit) << originalBits) + ((g2 & secretBitsDigit) << originalBits) + ((g3 & secretBitsDigit) << originalBits)); byte b = (byte)(((b1 & secretBitsDigit) << originalBits) + ((b2 & secretBitsDigit) << originalBits) + ((b3 & secretBitsDigit) << originalBits)); Color col = Color.FromArgb(r, g, b); return col; } 

This function is performed for each triples of the corresponding pixels of the image containers.

Secret image after recovery:


But what happens if at least one of the images does not contain the necessary encrypted data:

The same result will be obtained if, before recovery, to play with scaling images.

But if you resave images in JPEG with medium quality, and then again in BMP, then this will almost not cause additional distortion:


Results


To recover the image encoded by the described method, it is necessary to use all three container images obtained as a result of encryption. Otherwise, instead of the reconstructed image, we get only color noise.
The obvious disadvantage of the method is the distortion of the colors of the secret image during encryption (after all, only two high-order bits of eight are used). Of course, no one bothers us to increase the number of encrypted bits, but this will already affect the quality of the image containers.

Source: https://habr.com/ru/post/121878/


All Articles