What makes LSBit steganography detectable? And what would help in concealing it? In a project of mine I took a 24-bit bitmap image and I performed LSBit steganography over it (saved a black and white image inside each of the planes R, G, B) using pixel shuffling and xor encryption.

Is my stenography easy to detect? And what would it take to conceal it?
A general theoretical answer to the title's What makes LSBit steganography detectable? is that in normal images, the LSBit of a pixel in some channel is correlated to higher-order bits in the same pixel and channel, that pixel in other channels, and adjacent pixels, in ways that mere replacement of LSBit tends to strongly alter.

One simple way to improve that is adding noise or blurr to a degree such that the LSBit is nearly indistinguishable from random, in which case it can then be replaced by something equally indistinguishable from random (as resulting from good encryption) with little chance of detection versus an equally noisy/blurry image. Next step is changing only few bits at locations dependent on a key (towards that goal it is necessary to have a small payload, as previously pointed), and have the other pixels randomly noisy according to a good model of the natural image.

From a practical standpoint, sending uncompressed 24-bit bitmap images somewhat is a red flag that basic stego is in use. That would be somewhat less apparent with an additional step of JPEG lossless compression, or PNG or GIF conversion (lossy compression would destroy the hidden message given the LSBit encoding used; more sophisticated stenographic schemes survive that). Notice that sending noisy/blurry images without lossy compression is a waste of bandwidth, and could also raise alarm.

I suggest two "easy to detect" tests, to be applied comparatively on your image with stego (after decompression if a lossless compression step is added), and normal images that could be allegedly sent, at least including the one you start from.


Show as an 8-color image the 3 LSBits of each pixel; that can be done by changing each byte x in each RGB plane to ~((x&amp;1)-1). It there something perceptibly remarkable for your image with stego? Update: a 64 or 512-color image using (x&lt;&lt;6)+32 or (x&lt;&lt;5)+16 might also be interesting. (note:  the three expressions are for C, and assume truncation to octet. ~((x&amp;1)-1) yields 0x00 if the low bit of x is clear, 0xFF otherwise).
Is the compression ratio of PNG markedly lower for your image with stego than for normal images?


Note that these tests can only demonstrate failure to be undetectable.