I have a ciphertext of length n and I would like to XOR each bit of this ciphertext with the 2nd LSB of the bytes in an image and put the result in the LSB of the same byte of the image.
I like to continue this operation until ciphertext reaches the end.
I read the image into a byte array like bellow:
string cipherText = "some cipher text";
string address = this.picBoxOriginalImg.ImageLocation;
byte[] array = File.ReadAllBytes(address);
//this line gives me the list of all bits separated by a comma(just for visualization of the results for myself)
this.txtBoxTestByte.Text = string.Join(",", array.Select(b => Convert.ToString(b,2).ToUpper()));
But from here on I can't come up with a solution to XOR the bits of the cipherText
with the 2nd LSB of my image bytes, and replace the result with the LSB of the same byte.
Any help or code snippet will be much appreciated.
This does what you want. Explanations at the bottom.
static Bitmap Embed(string fname, string message)
{
Bitmap img = new Bitmap(fname);
byte[] msgBytes = System.Text.Encoding.UTF8.GetBytes(message);
int nbytes = msgBytes.Length;
int ibit = 7;
int ibyte = 0;
byte currentByte = msgBytes[ibyte];
for (int i = 0; i < img.Height; i++)
{
for (int j = 0; j < img.Width; j++)
{
Color pixel = img.GetPixel(i, j);
int lsb = (msgBytes[ibyte] >> ibit) & 1;
Color newpixel = Color.FromArgb(pixel.A, pixel.R, pixel.G, pixel.B ^ (lsb << 1));
img.SetPixel(i, j, newpixel);
ibit--;
if (ibit == -1)
{
ibit = 7;
ibyte++;
if (ibyte == nbytes)
{
return img;
}
currentByte = msgBytes[ibyte];
}
}
}
return img;
}
The ibyte
-ibit
combination iterates over your bytes and for each byte, it extracts the bits from the most significant to the least significant.
The bit extraction is done using the bitwise SHIFT and AND operations. Very briefly, the right shift brings the bit of interest to the least significant position and the AND operation masks out every other bit. This leaves with either a 0 or 1 depending on the value of your bit of interest. This is the meaning of int lsb = msgBytes[ibyte] >> ibit) & 1
.
Similarly, for the embedding, a left shift brings your bit to the second lsb position, so you either get 00000000, or 00000010. XORing something with 0 returns the same something so you don't have to worry about what the values of the other 7 bits are. You can go ahead and XOR the above with a pixel. All of this is summarised in (pixel.B ^ (lsb << 1)
.
I chose to embed the information in the blue channel, but feel free to change that. Keep in mind that if you do the embedding in the alpha channel, you will need to save the image to a format that supports transparency, e.g. png. Similarly, since you deal with direct pixel modifications, you can't save your image to a lossy format, e.g. jpeg, because the compression will modify some pixels and possibly destroy your information.