gifshuffle - GIF colourmap steganography program
] [ -p passwd
] [ -f
| -m message
] [ infile.gif
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 1675 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.
- Start with the message you want to conceal, specified on
the command line or in a file. Optionally compress and/or encrypt this
message. You are then left with a sequence of 1's and
- Prepend a 1 to this sequence, giving you a binary
number m (probably quite large).
- Next take a look at the GIF image that you want to conceal
the message in. Count the number of unique colours in the image, and call
the value n. If m > n!-1 then the message is too
large, and the procedure will be aborted.
- The colours in the colourmap are first sorted into their
"natural" order (except when encryption is being used - see
details below). Each RGB colour is assigned the value (red * 65536 + green
* 256 + blue), and the colours are sorted according to these values. Any
duplicate colours are removed.
- Iterate i through the values 1 .. n. Each
colour i-1 is allocated a target position ( m mod i),
then m is divided by i.
- Each colour is then in turn inserted into a new colourmap
at its target position. Colours previously occupying the target position
and above are moved up one place.
- If the size of the colourmap is greater than the number of
unique colours, then the colourmap will be padded with the last colour
from the original colourmap.
- The image component of the GIF is then uncompressed, the
colour indices are re-mapped to the new colourmap, and the image is
re-compressed. For animated GIFs this is repeated for each image.
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.
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
will do a
much better job.
Encryption is also provided, using the ICE encryption algorithm in 1-bit
cipher-feedback (CFB) mode to encrypt the data (after compression). 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, this means 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
) use the -1
If a message string or message file are specified on the command-line,
will attempt to conceal the message in the file
if specified, or standard input otherwise. The resulting
file will be written to outfile.gif
if specified, or standard output if
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
- Compress the data if concealing, or uncompress it if
- Quiet mode. If not set, the program reports statistics such
as compression percentages and amount of available storage space
- Report on the amount of space available for hidden message
in the GIF colourmap. This is calculated from the number of unique colours
in the image.
- Retain compatibility with version 1 of gifshuffle by
ordering colours using their "natural" ordering, rather than
their encrypted ordering. This is only relevant if a password is
- -p password
- If this is set, the data will be encrypted with this
password during concealment, or decrypted during extraction.
- -f message-file
- The contents of this file will be concealed in the input
- -m message-string
- The contents of this string will be concealed in the input
GIF image. Note that, unless a newline is somehow included in the string,
a newline will not be printed when the message is extracted.
The following command will conceal the message "Meet me at 6" in the
, with compression, and encrypted with the password
"hello world". The resulting text will be stored in
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"
Note that the resulting message will not be terminated by a newline.
The storage capacity of a file can be determined with the -S
gifshuffle -S infile.gif
This application was written by Matthew Kwan, who can be reached at