Steganography in Python - Stepic
Asked Answered
O

1

7

Using Stepic 0.3. I am executing commands to encode a message into a JPG image. The code I use is the following:

from PIL import Image
import stepic

im = Image.open ("tester.jpg")
im2 = stepic.encode(im, '0987639987069730979076409784690y7689734')
im2.save('stegtest.jpg')
im1 = Image.open('stegtest.jpg')
s = stepic.decode(im1) 
print s
data = s.decode() 
print data

Yet the print S and print data give me a value like: 6` or some other weird charcter. I think I am using the functions as theyre supposed to be used, why don't I get proper results?

Overzealous answered 30/5, 2013 at 14:4 Comment(2)
Perhaps the problem lies in the fact that JPG is a lossy format, and the steganographic scheme in stepic can't deal with the errors introduced by the compression. It works for PNG images, for instance.Rattlebrain
Yes that was it. Weird, because I have seen some examples where .jpg files are used. Worked flawlessly with .png Images! Thanks!Overzealous
R
6

stepic 0.3 uses the simplest approach to steganography in images. Quoting directly from the module:

def decode_imdata(imdata):
    '''Given a sequence of pixels, returns an iterator of characters
    encoded in the image'''

    imdata = iter(imdata)
    while True:
        pixels = list(imdata.next()[:3] + imdata.next()[:3] + imdata.next()[:3])
        byte = 0
        for c in xrange(7):
            byte |= pixels[c] & 1
            byte <<= 1
        byte |= pixels[7] & 1
        yield chr(byte)
        if pixels[-1] & 1:
            break

Every octet of the secret data, plus a flag whether it's the last byte, is hidden in three consecutive pixels. To be more precise, stepic uses the least significant bits of the first three components (often RGB) of each pixel. See this very ugly diagram, for an RGBA stream with 4 bits per component (D means data, E means end-of-stream):

                   | pixel 0             | pixel 1             | pixel 2             |
image viewer sees: | rrrr gggg bbbb aaaa | rrrr gggg bbbb aaaa | rrrr gggg bbbb aaaa |
stepic sees:       | ___D ___D ___D ____ | ___D ___D ___D ____ | ___D ___D ___E ____ |

Because the noise introduced by this change is small in already "noisy" images (one 256th), you often can't really detect this visually. That means the goal of this technique is achieved: the data is hidden in plain sight, because nobody can distinguish it from naturally occurring noise.

This works. At least, it works for lossless formats, such as PNG. Alas, JPG is not lossless, and its compression will very likely change at least one of the encoded bits. It suffices to change the ninth bit to render this method pretty useless, since then the hidden data will be truncated to a single byte.

Steganography in JPG images is still possible, in many forms, but you can't really just tweak the decoded pixel values. A better (but more complicated) method might be to hide data in the parameters estimated by the compressor.

Rattlebrain answered 30/5, 2013 at 15:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.