Design Build Test Repeat

Voluntarily cast upon the waves of outrageous fortune, this lowly geek flops from peak to peak of the technological ocean. Linux, Windows, C, Ruby, Python and embedded systems all attempt to pull our stalwart hero down. Will he survive alone or will the lifeboat of corporate servitude be too tempting.

Steganography in Python

Posted by Diarmuid on November 7, 2007

I am doing allot of work in python at the moment. I’m using Turbogears, SQLObject, pyftpdlib, and the Python Imaging Library. These are a great combination and I feel that I am the most productive I have been in a while. I am storing my images on Amazon S3 with the security set to public read so that I can directly link to them on my website. The Image name includes date-time info. as well as a random component, so that they cannot be read directly (at least not easily) without knowing the file name exactly.

I want to store extra info with the image and toyed with EXIF data but I came across the concept of Steganography recently. It allows for the storing of text or image data within an existing image without the image of the original being affected (it is a little bit but you’d be doing well to notice). I am thinking that this could be used to store date time info, motion info, previous image names, etc. There is a nice class that does this simply. It is Stepic. It is a fairly basic implementation in that it does no encryption or compression of the data but is more than adequate for my needs.

The way that I use it is first to install the PIL then use it as below. I could not get it to work on windows with the command line but from within a class it is fine.

>>>import Image
>>>import stepic
>>>im =‘in.jpg’)
>>>s = stepic.Steganographer(im)
>>> im2 = s.encode(‘This is some cool text’)
>>> s = stepic.decode(im2)
>>> data = s.decode()
>>> print data
This is some cool text


6 Responses to “Steganography in Python”

  1. Lenny said

    Wow, it’s cool that somebody is using Stepic for something real.

    Just a note, if you’re only making 1 image+data for each input image, you don’t have to manually make a Steganographer instance. You can just do im2 = stepic.encode(im, 'This is some cool text').

    If you’re using this in an automated production environment, are you guaranteeing that the images are large enough to store the data?

    I haven’t been actively changing the code (I think it’s stable, but there are some TODOs I haven’t touched). If you find any bugs, I’d happily take bug reports or patches.

  2. Diarmuid said


    Man, That was quick. The two of us are probably the only two in the whole webosphere that used the word “Steganography” today!!!

    I was thinking that maybe you could pass in an MD5 hash an that the get next pixel method would use that to determine where it would go next. There would be no guarantee that an allready modified pixel would not be remodified but the chances and consequences would be low.

    The images are 640×480 and the amount of text is low. How much is possible.

    Have a look at the command line as that didn’t work for me. I didn’t investigate at it may well have been my problem

    Well done anyway and thanks for the code and the tip. BTW, I got the link off the PIL news page today.



  3. Lenny said

    Quickness is due to pingback.

    640×480 should be enough for small text. Each character is spread across 3 pixels.

    You’re probably having trouble with the command line because you are saving JPEGs. Since JPEG is lossy, it doesn’t preserve the exact values Stepic uses. A good output format for Stepic is PNG–if that makes the files too large, this type of steganography is probably not right for the application.

    Yep, I assumed you got the link from Daily Python URL, since that link Xtupled traffic to my site, where X is a single digit number that depends on what metric you look at.

    Have you read the explanation of how Stepic works?

  4. Lenny said

    Oops, I meant to respond to your ‘hashing points to next pixel’ idea. When I was writing Stepic, I actually thought about doing either hashing or just plain linking to indicate the location of the next pixel, but I decided that it’s not necessary. Steganography is not encryption–anybody who suspects that data is hidden in an image will find it, whether the significant pixels are sequential or linked. Of course, you can just use real encoding as the first step, then use steganography.

  5. vkm said


    I tried following with the stenography code provided in your site.

    – opened a binary file
    – read few lines
    – wrote those files in the image file opened
    – tried to decode

    But it couldn’t decode that. Does this code work for binary content as well? I got the following error:
    File “”, line 1, in
    UnicodeDecodeError: ‘ascii’ codec can’t decode byte 0xc3 in position 12: ordinal not in range(128)


  6. Carlos said


    You are wrong.
    Stepic doesn’t work for JPEG files(
    The reason: JPEG are not lossles format.
    Your program runs because you use the same variable to decode (without read the file another time). If you don’t beleave me, try this:
    import Image
    import stepic
    im =’in.jpg’)
    s = stepic.Steganographer(im)
    im2 = s.encode(’This is some cool text’)’out.jpg’,’JPEG’)
    im3 =’out.jpg’)
    s = stepic.decode(im3)
    data = s.decode()
    print data

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: