1993-03-18 - a steganographic test

Header Data

From: Eli Brandt <ebrandt@jarthur.Claremont.EDU>
To: cypherpunks@toad.com
Message Hash: d1a10f2ffbddc019adb07c5e6e2703bde60254d68ed88584c0ae29838a025cf6
Message ID: <9303182224.AA05626@toad.com>
Reply To: N/A
UTC Datetime: 1993-03-18 22:24:39 UTC
Raw Date: Thu, 18 Mar 93 14:24:39 PST

Raw message

From: Eli Brandt <ebrandt@jarthur.Claremont.EDU>
Date: Thu, 18 Mar 93 14:24:39 PST
To: cypherpunks@toad.com
Subject: a steganographic test
Message-ID: <9303182224.AA05626@toad.com>
MIME-Version: 1.0
Content-Type: text/plain

Taking the easy way out, I tried a steganographic encoding in a GIF
by mapping down to 128 colors, duplicating them, and frobbing the
low bits of the image.  This worked surprisingly well.  The
resulting image showed little degradation, and was smaller than the
original -- the information thrown out when mapping down to 128 was
not fully replaced, as the "hidden" file did not fill the GIF.

Rather than screw with GIF and Heckbert code for this throwaway, I
did the {en,de}giffing and palette manipulation by hand with the PC
program PICLAB.  It supports scripts, which would automate the
process, except for the palette duplication, which a sed script
could do.  The bit bashing code is appended, though it's pretty
trivial stuff.

Anyway, I ended up with the canonical Earth-seen-from-space,
320x200x8, with an embedded DOS-format text file chosen for
verisimilitude.  I can ship it by e-mail to anyone who wants it,
though there's not really a whole lot you can *do* with the thing.
("Hey.  Wow.  There really is a file in the low bits.")

	 PGP 2 key by finger or e-mail
   Eli   ebrandt@jarthur.claremont.edu

	the guts of ensteg.c:
 * We smear the hidef stream MSB-first into the low bits of the picf stream.
 * This code is not optimal, but hey, it's short.
   int picbyte, hidebyte, mask=0;
   long count=0;

   while (EOF!=(picbyte=getc(picf)))  {
      if (!mask)  {
	 mask = 0x80;
	 if (EOF==(hidebyte=getc(hidef)))
	    hidebyte=0;			// pad with nulls
      putc(picbyte&0xfe | ((hidebyte&mask)/mask), outf);


	and of desteg.c:
 * Pull the picf bits out, and put them together, MSB-LSB order.
   int picbyte, hidebyte=0, bit=7;

   while (EOF!=(picbyte=getc(picf)))  {
      if (bit<0)  {
	 putc(hidebyte, hidef);
      hidebyte |= (picbyte%2)<<bit--;
   if (bit<0)  putc(hidebyte, hidef);

Caveats: no error checking.  The pic file had better be eight times
as large as the file to put in it.  If the null-padding will cause
problems, you should wrap the file with an archiver first.

Sorry about that putc() line in ensteg.c; it was late.