user2436704
user2436704

Reputation: 71

Steganography in Python - Stepic

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?

Upvotes: 7

Views: 6682

Answers (1)

user824425
user824425

Reputation:

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.

Upvotes: 6

Related Questions