Blame view

msteg/steganography/LSB.py 3.5 KB
6cbb3879   Chunk   F4 updated.
1
2
"""
<p>This plugin implements two variants of a well-known steganographic
548d95dc   Chunk   steganography(F3 ...
3
4
procedure commonly referred to as LSB algorithm.</p>
The general idea is to
b69b6985   Chunk   py module refract...
5
overwrite some portion (usually the k least significant bits) of each byte
c9fdeb00   Chunk   LSB and F4 added.
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
in the cover image. The below methods specify the number of overwritten
bits a parameter named word_size. Thus --- in this context --- word means
\"a group of bits of a fixed size\".
"""
import time
import numpy as np
import scipy as sp
from StegBase import *
from common import *


class LSB(StegBase):
    """ This module has two methods: <i>embed_raw_data</i> to embed data
    with the F3 algorithm and <i>extract_raw_data</i> to extract data
    which was embedded previously. """

    def __init__(self):
        """
        Constructor of the F3 class.
        """
        StegBase.__init__(self)

    def embed_raw_data(self, src_cover, src_hidden, tgt_stego):
548d95dc   Chunk   steganography(F3 ...
29
        """ This method embeds arbitrary data into a cover image.
c9fdeb00   Chunk   LSB and F4 added.
30
31
32
        The cover image must be a JPEG.

        src_cover - A valid pathname to an image file which serves as cover image
548d95dc   Chunk   steganography(F3 ...
33
        (the image which the secret image is embedded into).
c9fdeb00   Chunk   LSB and F4 added.
34
35
36
37
38
39
40
41
42
43
44
45
46
47

        src_hidden - A valid pathname to an arbitrary file that is supposed to be
        embedded into the cover image.

        tgt_stego - Target pathname of the resulting stego image. You should save to a
        PNG or another lossless format, because many LSBs don't survive
        lossy compression.
        """
        self.t0 = time.time()
        StegBase._post_embed_actions(self, src_cover, src_hidden, tgt_stego)

    def extract_raw_data(self, src_steg, tgt_hidden):
        """ This method extracts secret data from a stego image. It is
        (obviously) the inverse operation of embed_raw_data.
6cbb3879   Chunk   F4 updated.
48

548d95dc   Chunk   steganography(F3 ...
49
        src_stego - A valid pathname to an image file which serves as stego image.
c9fdeb00   Chunk   LSB and F4 added.
50
51
52
53
54
55
56
57
58
59
60

        tgt_hidden - A pathname denoting where the extracted data should be saved to.
        """
        self.t0 = time.time()
        StegBase._post_extract_actions(self, src_steg, tgt_hidden)

    def _raw_embed(self, cov_data, hid_data, status_begin=0):
        """
        cov_data - 4-D numpy.int32 array
        hid_data - 1-D numpy.uint8 array
        """
45a82355   Chunk   staged.
61
        hid_data = bytes2bits(hid_data)
c9fdeb00   Chunk   LSB and F4 added.
62
63
64
65
66
67
        i = 0
        cnt = -1
        for x in np.nditer(cov_data, op_flags=['readwrite']):
            cnt = cnt + 1
            if x == 0 or x == 1 or cnt % 64 == 0: continue

548d95dc   Chunk   steganography(F3 ...
68
            m = (hid_data[i] & 1)
c9fdeb00   Chunk   LSB and F4 added.
69
            x[...] = (x & 0xfffffffe) | m
548d95dc   Chunk   steganography(F3 ...
70
            i += 1
c9fdeb00   Chunk   LSB and F4 added.
71
72
73
74
75
76
77
78
79
80
81
            if i == hid_data.size: break

        return cov_data

    def _raw_extract(self, steg_data, num_bits):
        """
        Just a small helper function to extract hidden data.
        """
        hid_data = np.zeros(num_bits, np.uint8)
        j = 0
        cnt = -1
548d95dc   Chunk   steganography(F3 ...
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
        for x in np.nditer(steg_data):
            cnt = cnt + 1
            if x == 0 or x == 1 or cnt % 64 == 0: continue
            if j >= num_bits: break
            hid_data[j] = x & 1
            j = j + 1

        return hid_data

    def __str__(self):
        return 'LSB'


# this function might be a candidate for some kind of util module
def _parse_boolean(b):
    """Turns a boolean value into a string if it is not already a boolean.