Twitter steganography: decoding messages hidden in images​
​by Robert Rimmer
If you post an image with a tweet that is not too large, Twitter will accept a PNG image and preserve its byte structure. This feature can be used to encode information in the least significant bit [LSB] with a message as in the image below.
In[]:=
img=Import["https://pbs.twimg.com/media/E-Onr_MXsAE7p5F?format=png&name=360x360"]
Out[]=
If you post a large file, Twitter will crush it with JPEG processing and your information will be lost. The image above was cropped and ImageResize[]d to make it smaller. The original cell phone camera image was very much larger. Some of the information content from the larger image’s LSB is shown below. There are some patterns in the data which might be usable to identify it as a JPEG, the entropy is much lower than it would be for random data.
In[]:=
SetDirectory[NotebookDirectory[]];​​FileSize["20210831_145128.jpg"]​​bigimg=Import["20210831_145128.jpg"];​​bigimgData=Flatten[ImageData[bigimg,"Byte"]];​​Length@%(*Expandedimagebytecount*)​​Histogram[FromDigits[#,2]&/@Partition[Mod[bigimgData,2],8],{1},PlotLabel->"Byte Frequencies in LSB"]​​Entropy[2.,FromDigits[#,2]&/@Partition[Mod[bigimgData,2],8]]
Out[]=
2.48141
MB
Out[]=
27433728
Out[]=
Out[]=
6.7614
Here are the characteristics of the LSB in the dog image. The message was encoded in groups of seven bits. The pattern is clearly consistent with ASCII encoding of English text.
In[]:=
imgData=Flatten[ImageData[img,"Byte"]];​​Length@%(*Expandedimagebytecount*)​​Histogram[FromDigits[#,2]&/@Partition[Mod[imgData,2],7],{1},PlotLabel->"7 Bit ASCII Frequencies in LSB"]​​Entropy[2.,FromDigits[#,2]&/@Partition[Mod[imgData,2],7]]
Out[]=
334668
Out[]=
Out[]=
4.46123
The code below extracts the least significant bit of each byte of the RGBColor data. Since the picture is longer than the message, the remainder is removed so the code will align properly with multiples of 7 bits.
In[]:=
remainder=Mod[Length[imgData],7]
Out[]=
5
This line of code extracts the message from the picture . The entire text of the United States Constitution was encoded in the picture.
In[]:=
FromCharacterCode[IntegerDigits[FromDigits[Mod[Drop[imgData,-remainder],2],2],128]]
Here is a new version of the dog image which contains a notebook that shows how to create a message in the least significant bit of each RGBColor byte.
In[]:=
nbimg=
;​​byteCode=FromDigits[#,2]&/@Partition[Mod[Take[Flatten[ImageData[nbimg,"Byte"]],136080],2],8];
Evaluate the next line to open the notebook in a new window.
In[]:=
NotebookPut[ImportString[ByteArrayToString[ByteArray[byteCode]],"NB"]]
Anything can be put into the least significant bit of a photographic image without much changing the image. If the image is saved in PNG or other lossless format, the information can be preserved in the image. Encrypted also messages can easily be saved in the LSB. Cryptographic keys can also be exchanged in images. I doubt there is anything that can prevent this from happening, on social media and forums such as Wolfram Community. Mathematica users can easily make use of this communication channel.