StegBase.py
4.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
"""
This module implements a common base class of the steganographic
algorithms which embed data into JPEG files.
In order to run plugins inheriting from this class
you must build the rw_dct.so library which interfaces with libjpeg.
To do so, just run
% python setup.py build
in stegotool/util and copy the rw_dct.so
library (which can be found somewhere in the build-directory to
stegotool/util.
"""
import numpy as np
import time
import os
import sys
import random
import re
import mjsteg
import jpegObj
from common import *
class StegBase(object):
"""
This is the base class for some of the JPEG-algorithms that behave
similarly such as JSteg, OutGuess and F3.
"""
def __init__(self):
"""
Constructor of the JPEGSteg class.
"""
self.t0 = None
self.cov_jpeg = None
self.cov_data = None
self.hid_data = None
def _get_cov_data(self, img_path):
"""
Returns DCT coefficients of the cover image.
"""
self.cov_jpeg = jpegObj.Jpeg(img_path)
self.cov_data = self.cov_jpeg.getCoefBlocks()
return self.cov_data
def _get_hid_data(self, src_hidden):
"""
Returnsthe secret data as byte sequence.
"""
raw = [0, 0, 0, 0] + np.fromfile(src_hidden, np.uint8).tolist()
raw_size = len(raw)
for i in xrange(4):
raw[i] = raw_size % 256
raw_size /= 256
self.hid_data = np.array(raw)
if np.size(self.hid_data) * 8 > np.size(self.cov_data):
raise Exception("Cover image is too small to embed data.Cannot fit %d bits in %d DCT coefficients" % (
np.size(self.hid_data) * 8, np.size(self.cov_data)))
return self.hid_data
def _post_embed_actions(self, src_cover, src_hidden, tgt_stego):
"""
This function isn't named very accurately. It actually calls the
_raw_embed function in inherited classes.
"""
try:
cov_data = self._get_cov_data(src_cover)
hid_data = self._get_hid_data(src_hidden)
cov_data = self._raw_embed(cov_data, hid_data)
self.cov_jpeg.setCoefBlocks(cov_data)
self.cov_jpeg.Jwrite(tgt_stego)
size = os.path.getsize(tgt_stego)
size_embedded = np.size(hid_data)
self._display_stats("embedded", size, size_embedded,
time.time() - self.t0)
except TypeError as e:
raise e
except Exception:
raise Exception(
'DCT coefficients exhausted. This usually means there are not enough DCT coefficients in the image in which algorithm can actually embed data. You should choose a larger image.')
def _post_extract_actions(self, src_steg, tgt_hidden):
"""
This function isn't named very accurately. It actually calls the
_raw_extract function in inherited classes.
"""
try:
steg_data = self._get_cov_data(src_steg)
emb_size = os.path.getsize(src_steg)
# recovering file size
header_size = 4 * 8
size_data = self._raw_extract(steg_data, header_size)
size_data = bits2bytes(size_data)
size_hd = 0
for i in xrange(4):
size_hd += size_data[i] * 256 ** i
raw_size = size_hd * 8
if raw_size > np.size(steg_data):
raise Exception("Supposed secret data too large for stego image.")
hid_data = self._raw_extract(steg_data, raw_size)
hid_data = bits2bytes(hid_data)
hid_data[4:].tofile(tgt_hidden)
self._display_stats("extracted", emb_size,
np.size(hid_data),
time.time() - self.t0)
except:
raise Exception('DCT coefficients exhausted.The stego image is probably corrupted.')
def _looks_like_jpeg(self, path):
try:
with open(path, 'r') as f:
return f.read(2) == '\xff\xd8'
except IOError:
return False
def _display_stats(self, verb, cov_size, emb_size, duration):
print(
"%dB %s in %.2fs (%.2f kBps), embedding ratio: %.4f" %
(emb_size, verb, duration, (emb_size / duration) / 1000.,
float(emb_size) / cov_size))
# dummy functions to please pylint
def _raw_embed(self, cov_data, hid_data, status_begin=0):
pass
def _raw_extract(self, steg_data, num_bits):
pass
def _dummy_embed_hook(self, cov_data, hid_data):
pass
def _dummy_extract_hook(self, steg_data, num_bits):
pass