gifshuffle is a program for concealing messages in GIF images by shuffling the colourmap. A shuffled image is visibly indistinguishable from the original. gifshuffle works with all GIF images, including those with transparency and animation.
Consider a pack of 52 cards. There are 52 factorial ways to sort the pack, which means that any particular ordering of the cards can represent a number in the range [0, 52!-1]. In other words, given n cards, you can store approximately log2(n!) bits of information based on their ordering.
GIF images contain a colourmap with up to 256 entries, resulting in a maximum storage capacity of 1683 bits. The image itself consists of a compressed array of indices into this colourmap. To conceal a message within a GIF image the following steps take place.
Extracting a hidden message follows a similar procedure, but in reverse. The ordering of the colourmap is used to construct a binary number, which is then optionally decrypted and uncompressed before being output.
gifshuffle provides rudimentary compression, using Huffman tables optimised for English text. However, if the data is not text, or if there is a lot of data, the use of the built-in compression is not recommended, since an external compression program such as compress or gzip will do a much better job.
Encryption is also provided, using the ICE encryption algorithm in 1-bit cipher-feedback (CFB) mode. Because of ICE's arbitrary key size, passwords of any length up to 1170 characters are supported (since only 7 bits of each character are used, keys up to 1024-bytes are supported).
As of gifshuffle 2.0 encryption is also applied to the ordering of the colours in the colourmap. Instead of using their "natural" ordering, the ordering of their encrypted hash is used. This has the benefit of making colourmaps look random even when there is only a small message concealed. To disable this feature (which is incompatible with version 1 of gifshuffle) use the -1 option.
If a message string or message file are specified on the command-line, gifshuffle will attempt to conceal the message in the file infile.gif if specified, or standard input otherwise. The resulting file will be written to outfile.gif if specified, or standard output if not.
If no message string is provided, gifshuffle attempts to extract a message from the input file. The result is written to the output file or standard output.
The following command will conceal the message "Meet me at 6" in the file infile.gif, with compression, and encrypted with the password "hello world". The resulting text will be stored in outfile.gif.
gifshuffle -C -m "Meet me at 6" -p "hello world" infile.gif outfile.gif
To extract the message, the command would be
gifshuffle -C -p "hello world" outfile.gif
Note that the resulting message will not be terminated by a newline.
The approximate storage capacity of a file can be determined with the -S option.
gifshuffle -S infile.gif