Commit 8cfc1a2373c0fb2aa9b6fcbd6a4e795f3ac76320

Authored by Chunk
1 parent 033d3b0d
Exists in master

F5 half-finished.

jpegObj/__init__.pyc
No preview for this file type
msteg/StegBase.py
@@ -102,6 +102,10 @@ class StegBase(object): @@ -102,6 +102,10 @@ class StegBase(object):
102 # recovering file size 102 # recovering file size
103 header_size = 4 * 8 103 header_size = 4 * 8
104 size_data, bits_cnt = self._raw_extract(steg_data, header_size) 104 size_data, bits_cnt = self._raw_extract(steg_data, header_size)
  105 + if bits_cnt < header_size:
  106 + raise Exception("Expected embedded size is %db but actually %db." % (
  107 + header_size, bits_cnt))
  108 +
105 size_data = bits2bytes(size_data) 109 size_data = bits2bytes(size_data)
106 size_hd = 0 110 size_hd = 0
107 for i in xrange(4): 111 for i in xrange(4):
msteg/StegBase.pyc
No preview for this file type
msteg/steganography/F3.pyc
No preview for this file type
msteg/steganography/F4-simple.py 0 → 100644
@@ -0,0 +1,101 @@ @@ -0,0 +1,101 @@
  1 +__author__ = 'chunk'
  2 +
  3 +"""
  4 +<p>This module implements a slight variant of the F4 steganography algorithm
  5 +invented by Andreas Westfeld. It embeds a secret message in JPEG
  6 +DCT coefficients.</p>
  7 +It differs from F3 in that even negative and odd positive DCT
  8 +coefficients represent a 1 and odd negative and even positive
  9 +DCT coefficients represent a 0. It also supports permutative strattling
  10 +which is not included in the original description of F4.
  11 +"""
  12 +import time
  13 +import numpy as np
  14 +from msteg.StegBase import StegBase
  15 +from common import *
  16 +
  17 +
  18 +class F4(StegBase):
  19 + """ This module has two methods: <i>embed_raw_data</i> to embed data
  20 + with the F3 algorithm and <i>extract_raw_data</i> to extract data
  21 + which was embedded previously. """
  22 +
  23 + def __init__(self):
  24 + """
  25 + Constructor of the F3 class.
  26 + """
  27 + StegBase.__init__(self)
  28 +
  29 + def embed_raw_data(self, src_cover, src_hidden, tgt_stego):
  30 + """ This method embeds arbitrary data into a cover image.
  31 + The cover image must be a JPEG.
  32 +
  33 + src_cover - A valid pathname to an image file which serves as cover image
  34 + (the image which the secret image is embedded into).
  35 +
  36 + src_hidden - A valid pathname to an arbitrary file that is supposed to be
  37 + embedded into the cover image.
  38 +
  39 + tgt_stego - Target pathname of the resulting stego image. You should save to a
  40 + PNG or another lossless format, because many LSBs don't survive
  41 + lossy compression.
  42 + """
  43 + self.t0 = time.time()
  44 + StegBase._post_embed_actions(self, src_cover, src_hidden, tgt_stego)
  45 +
  46 + def extract_raw_data(self, src_steg, tgt_hidden):
  47 + """ This method extracts secret data from a stego image. It is
  48 + (obviously) the inverse operation of embed_raw_data.
  49 +
  50 + src_stego - A valid pathname to an image file which serves as stego image.
  51 +
  52 + tgt_hidden - A pathname denoting where the extracted data should be saved to.
  53 + """
  54 + self.t0 = time.time()
  55 + StegBase._post_extract_actions(self, src_steg, tgt_hidden)
  56 +
  57 + def _raw_embed(self, cov_data, hid_data, status_begin=0):
  58 + """
  59 + cov_data - 4-D numpy.int32 array
  60 + hid_data - 1-D numpy.uint8 array
  61 + """
  62 + hid_data = bytes2bits(hid_data)
  63 + i = 0
  64 + cnt = -1
  65 + for x in np.nditer(cov_data, op_flags=['readwrite']):
  66 + cnt = cnt + 1
  67 + if x == 0 or cnt % 64 == 0: continue
  68 +
  69 + m = (hid_data[i] & 1)
  70 + if x > 0 and x & 1 != m:
  71 + x[...] -= 1
  72 + elif x < 0 and x & 1 == m:
  73 + x[...] += 1
  74 + if x == 0: continue
  75 + i += 1
  76 + if i == hid_data.size: break
  77 +
  78 + return cov_data
  79 +
  80 + def _raw_extract(self, steg_data, num_bits):
  81 + """
  82 + Just a small helper function to extract hidden data.
  83 + """
  84 + hid_data = np.zeros(num_bits, np.uint8)
  85 + j = 0
  86 + cnt = -1
  87 + for x in np.nditer(steg_data):
  88 + cnt = cnt + 1
  89 + if x == 0 or cnt % 64 == 0: continue
  90 + if j >= num_bits: break
  91 + if x > 0:
  92 + hid_data[j] = x & 1
  93 + else:
  94 + hid_data[j] = (x & 1) ^ 1
  95 +
  96 + j = j + 1
  97 +
  98 + return hid_data
  99 +
  100 + def __str__(self):
  101 + return "F4'"
msteg/steganography/F4.py
@@ -74,6 +74,10 @@ class F4(StegBase): @@ -74,6 +74,10 @@ class F4(StegBase):
74 # recovering file size 74 # recovering file size
75 header_size = 4 * 8 75 header_size = 4 * 8
76 size_data, bits_cnt = self._raw_extract(steg_data, header_size) 76 size_data, bits_cnt = self._raw_extract(steg_data, header_size)
  77 + if bits_cnt < header_size:
  78 + raise Exception("Expected embedded size is %db but actually %db." % (
  79 + header_size, bits_cnt))
  80 +
77 size_data = bits2bytes(size_data) 81 size_data = bits2bytes(size_data)
78 82
79 size_hd = 0 83 size_hd = 0
@@ -120,6 +124,7 @@ class F4(StegBase): @@ -120,6 +124,7 @@ class F4(StegBase):
120 if x == 0: continue 124 if x == 0: continue
121 i += 1 125 i += 1
122 if i == hid_data.size: break 126 if i == hid_data.size: break
  127 +
123 return cov_data, i 128 return cov_data, i
124 129
125 def _raw_extract(self, steg_data, num_bits): 130 def _raw_extract(self, steg_data, num_bits):
@@ -127,6 +132,7 @@ class F4(StegBase): @@ -127,6 +132,7 @@ class F4(StegBase):
127 Just a small helper function to extract hidden data. 132 Just a small helper function to extract hidden data.
128 steg_data - 1-D numpy.int16 array (permunated) 133 steg_data - 1-D numpy.int16 array (permunated)
129 """ 134 """
  135 +
130 hid_data = np.zeros(num_bits, np.uint8) 136 hid_data = np.zeros(num_bits, np.uint8)
131 j = 0 137 j = 0
132 for x in steg_data: 138 for x in steg_data:
msteg/steganography/F4.pyc
No preview for this file type
msteg/steganography/F5.py
  1 +__author__ = 'chunk'
  2 +
1 """ 3 """
2 <p>This module implements the rather sophisticated F5 algorithm which was 4 <p>This module implements the rather sophisticated F5 algorithm which was
3 invented by Andreas Westfeld.</p> 5 invented by Andreas Westfeld.</p>
@@ -35,118 +37,134 @@ class F5(StegBase): @@ -35,118 +37,134 @@ class F5(StegBase):
35 with the F5 algorithm and <i>extract_raw_data</i> to extract data 37 with the F5 algorithm and <i>extract_raw_data</i> to extract data
36 which was embedded previously. """ 38 which was embedded previously. """
37 39
38 - def __init__(self, key=sample_key): 40 + def __init__(self, key=sample_key, k=None):
39 """ 41 """
40 Constructor of the F5 class. 42 Constructor of the F5 class.
41 """ 43 """
42 StegBase.__init__(self, key) 44 StegBase.__init__(self, key)
43 self._embed_fun = None 45 self._embed_fun = None
44 self.default_embedding = True 46 self.default_embedding = True
45 - self.steg_ind = -1  
46 - self.excess_bits = None 47 +
47 # needed because k is embedded separately 48 # needed because k is embedded separately
48 - self.cov_ind = -1  
49 - self.k_coeff = -1  
50 -  
51 - @describe_annotate_convert((None, None, ident),  
52 - ("cover image", ImagePath, str),  
53 - ("hidden data", FilePath, str),  
54 - ("stego image", NewFilePath, str),  
55 - ("seed", int, int),  
56 - ("embedding behavior",  
57 - ['Default', 'F3', 'JSteg'], str))  
58 - def embed_raw_data(self, src_cover, src_hidden, tgt_stego, seed,  
59 - embed_fun):  
60 - """<p>This method embeds arbitrary data into a cover image.  
61 - The cover image must be a JPEG.</p>  
62 -  
63 - <p>Parameters:  
64 - <ol>  
65 - <li><pre>src_cover</pre>  
66 - A valid pathname to an image file which serves as cover image  
67 - (the image which the secret image is embedded into).</li>  
68 -  
69 - <li><pre>src_hidden</pre>  
70 - A valid pathname to an arbitrary file that is supposed to be  
71 - embedded into the cover image.</li>  
72 -  
73 - <li><pre>tgt_stego</pre>  
74 - Target pathname of the resulting stego image. You should save to  
75 - a PNG or another lossless format, because many LSBs don't survive  
76 - lossy compression.</li>  
77 -  
78 - <li><pre>seed</pre>  
79 - A seed for the random number generator that is responsible scattering  
80 - the secret data within the cover image.</li>  
81 -  
82 - <li><pre>param embed_fun</pre> 49 + self.k_coeff = k
  50 +
  51 +
  52 + def _get_cov_data(self, img_path):
  53 + """
  54 + Returns DCT coefficients of the cover image.
  55 + """
  56 + self.cov_jpeg = jpegObj.Jpeg(img_path, key=self.key)
  57 +
  58 + cov_data = self.cov_jpeg.getsignal(channel='Y')
  59 + self.cov_data = np.array(cov_data, dtype=np.int16)
  60 + return self.cov_data
  61 +
  62 + def embed_raw_data(self, src_cover, src_hidden, tgt_stego, embed_fun='Default'):
  63 + """This method embeds arbitrary data into a cover image.
  64 + The cover image must be a JPEG.
  65 +
  66 + @param embed_fun:
83 Specifies which embedding function should be used. Must be one of 67 Specifies which embedding function should be used. Must be one of
84 'Default', 'F3', 'Jsteg'. If 'Default' is selected, the algorithm uses 68 'Default', 'F3', 'Jsteg'. If 'Default' is selected, the algorithm uses
85 the same behavior as Westfeld's implementation, i.e. decrementing 69 the same behavior as Westfeld's implementation, i.e. decrementing
86 absolute values for n > 1 (F3) and using F4 in the special case n = 1. 70 absolute values for n > 1 (F3) and using F4 in the special case n = 1.
87 - Selecting F3 or JSteg results in using that scheme for all n.</li>  
88 - </ol>  
89 - </p> 71 + Selecting F3 or JSteg results in using that scheme for all n.
90 """ 72 """
91 self.t0 = time.time() 73 self.t0 = time.time()
92 - self.seed = seed 74 +
93 if embed_fun == 'F3': 75 if embed_fun == 'F3':
94 self._embed_fun = self._f3_embed 76 self._embed_fun = self._f3_embed
95 self.default_embedding = False 77 self.default_embedding = False
96 - elif embed_fun == 'JSteg': 78 + elif embed_fun == 'JSteg' or embed_fun == 'LSB':
97 self._embed_fun = self._jsteg_embed 79 self._embed_fun = self._jsteg_embed
98 self.default_embedding = False 80 self.default_embedding = False
99 - elif embed_fun == 'Default': 81 + else:
100 self._embed_fun = self._f3_embed 82 self._embed_fun = self._f3_embed
101 self.default_embedding = True 83 self.default_embedding = True
102 84
103 - self.cov_ind = -1  
104 - JPEGSteg._post_embed_actions(self, src_cover, src_hidden, tgt_stego) 85 + try:
  86 + cov_data = self._get_cov_data(src_cover)
  87 + hid_data = self._get_hid_data(src_hidden)
  88 + # print hid_data.dtype,type(hid_data),hid_data.tolist()
105 89
106 - @describe_annotate_convert((None, None, ident),  
107 - ("stego image", ImagePath, str),  
108 - ("hidden data", NewFilePath, str),  
109 - ("seed", int, int),  
110 - ("embedding behavior", ['Default', 'F3/JSteg'],  
111 - str))  
112 - def extract_raw_data(self, src_steg, tgt_hidden, seed, embed_fun):  
113 - """<p>This method extracts secret data from a stego image. It is  
114 - (obviously) the inverse operation of embed_raw_data.</p> 90 + cov_data, bits_cnt = self._raw_embed(cov_data, hid_data)
115 91
116 - <p>Parameters:  
117 - <ol>  
118 - <li><pre>src_stego</pre>  
119 - A valid pathname to an image file which serves as stego image.</li> 92 + if bits_cnt < np.size(hid_data) * 8:
  93 + raise Exception("Expected embedded size is %db but actually %db." % (
  94 + np.size(hid_data) * 8, bits_cnt))
120 95
121 - <li><pre>tgt_hidden</pre>  
122 - A pathname denoting where the extracted data should be saved to.</li> 96 + self.cov_jpeg.setsignal(cov_data, channel='Y')
  97 + self.cov_jpeg.Jwrite(tgt_stego)
123 98
124 - <li><pre>param seed</pre>  
125 - A seed for the random number generator that is responsible scattering  
126 - the secret data within the cover image.</li> 99 + # size_cov = os.path.getsize(tgt_stego)
  100 + size_cov = np.size(cov_data) / 8
  101 + size_embedded = np.size(hid_data)
127 102
128 - <li><pre>param embed_fun</pre>  
129 - Specifies which embedding function should be used. Must be one of  
130 - 'Default', 'F3', 'JSteg'. If 'Default' is selected, the algorithm uses  
131 - the same behavior as Westfeld's implementation, i.e. decrementing  
132 - absolute values for n > 1 (F3) and using F4 in the special case n = 1.  
133 - Selecting F3 or JSteg results in using that scheme for all n.</li>  
134 - </ol></pre>  
135 - """ 103 + self._display_stats("embedded", size_cov, size_embedded,
  104 + time.time() - self.t0)
136 105
  106 + except TypeError as e:
  107 + raise e
  108 + except Exception as expt:
  109 + print "Exception when embedding!"
  110 + raise
  111 +
  112 +
  113 + def extract_raw_data(self, src_steg, tgt_hidden, embed_fun='Default'):
137 self.t0 = time.time() 114 self.t0 = time.time()
138 - self.seed = seed  
139 - self.steg_ind = -1  
140 - if embed_fun == 'F3/JSteg': 115 +
  116 + if embed_fun == 'F3':
  117 + self._embed_fun = self._f3_embed
  118 + self.default_embedding = False
  119 + elif embed_fun == 'JSteg' or embed_fun == 'LSB':
  120 + self._embed_fun = self._jsteg_embed
141 self.default_embedding = False 121 self.default_embedding = False
142 - elif embed_fun == 'Default': 122 + else:
  123 + self._embed_fun = self._f3_embed
143 self.default_embedding = True 124 self.default_embedding = True
144 125
145 - # excess bits occur when the size of extracted data is not a multiple  
146 - # of k. if excess bits are available, they are prepended to hidden data  
147 - self.excess_bits = None 126 + try:
  127 + steg_data = self._get_cov_data(src_steg)
  128 + # emb_size = os.path.getsize(src_steg)
  129 + emb_size = np.size(steg_data) / 8
  130 +
  131 + # recovering file size
  132 + header_size = 4 * 8
  133 + size_data, bits_cnt = self._raw_extract(steg_data, header_size)
  134 +
  135 + if bits_cnt < header_size:
  136 + raise Exception("Expected embedded size is %db but actually %db." % (
  137 + header_size, bits_cnt))
  138 +
  139 + size_data = bits2bytes(size_data[:header_size])
  140 + print size_data
  141 +
  142 + size_hd = 0
  143 + for i in xrange(4):
  144 + size_hd += size_data[i] * 256 ** i
  145 +
  146 + raw_size = size_hd * 8
  147 +
  148 + if raw_size > np.size(steg_data):
  149 + raise Exception("Supposed secret data too large for stego image.")
  150 +
  151 + hid_data, bits_cnt = self._raw_extract(steg_data, raw_size)
  152 +
  153 + if bits_cnt < raw_size:
  154 + raise Exception("Expected embedded size is %db but actually %db." % (
  155 + raw_size, bits_cnt))
  156 +
  157 + hid_data = bits2bytes(hid_data)
  158 + # print hid_data.dtype,type(hid_data),hid_data.tolist()
  159 + hid_data[4:].tofile(tgt_hidden)
  160 +
  161 + self._display_stats("extracted", emb_size,
  162 + np.size(hid_data),
  163 + time.time() - self.t0)
  164 + except Exception as expt:
  165 + print "Exception when extracting!"
  166 + raise
148 167
149 - JPEGSteg._post_extract_actions(self, src_steg, tgt_hidden)  
150 168
151 def _embed_k(self, cov_data, hid_data): 169 def _embed_k(self, cov_data, hid_data):
152 np.random.seed(self.seed) 170 np.random.seed(self.seed)
@@ -218,153 +236,89 @@ class F5(StegBase): @@ -218,153 +236,89 @@ class F5(StegBase):
218 236
219 def _jsteg_embed(self, cov_data, ind): 237 def _jsteg_embed(self, cov_data, ind):
220 m = 1 ^ (cov_data[ind] & 1) 238 m = 1 ^ (cov_data[ind] & 1)
221 - cov_data[ind] = (cov_data[ind] & 0xffffe) | m 239 + cov_data[ind] = (cov_data[ind] & 0xfffffffe) | m
222 240
223 - def _raw_embed(self, cov_data, hid_data, status_begin=0): 241 + def _raw_embed(self, cov_data, hid_data):
224 k = self.k_coeff 242 k = self.k_coeff
225 n = (1 << k) - 1 243 n = (1 << k) - 1
  244 +
226 if n == 1 and self.default_embedding: 245 if n == 1 and self.default_embedding:
227 - # in case k = n = 1, Westfeld's implementation uses F4 for  
228 - # embedding. Therefore, if 'default' embedding has been selected  
229 - # we will do the same  
230 - f4 = F4(self.ui, self.core)  
231 - f4.seed = self.seed  
232 - f4.dct_p = self.dct_p  
233 - f4.cov_ind = self.cov_ind  
234 - cov_data = f4._raw_embed(cov_data, hid_data, 30)  
235 - return cov_data  
236 -  
237 - cov_ind = self.cov_ind # preventing RSI by writing 'self' less often  
238 - hid_ind = 0  
239 - remaining_bits = hid_data.size  
240 - hid_size = float(hid_data.size)  
241 - dct_p = self.dct_p  
242 -  
243 - update_cnt = int(hid_size / (70.0 * k))  
244 - while remaining_bits > 0:  
245 - if update_cnt == 0:  
246 - self._set_progress(30 + int(((  
247 - hid_size - remaining_bits) / hid_size) * 70))  
248 - update_cnt = int(hid_size / (70.0 * k))  
249 - update_cnt -= 1  
250 - msg_chunk_size = min(remaining_bits, k)  
251 - msg_chunk = np.zeros(k, np.int8)  
252 - cov_chunk = np.zeros(n, np.int32)  
253 - msg_chunk[0:msg_chunk_size] = hid_data[hid_ind:hid_ind +  
254 - msg_chunk_size]  
255 - hid_ind += k  
256 -  
257 - # get n DCT coefficients  
258 - for i in xrange(n):  
259 - cov_ind += 1  
260 - while cov_data[dct_p[cov_ind]] == 0 \  
261 - or dct_p[cov_ind] % 64 == 0:  
262 - cov_ind += 1  
263 - cov_chunk[i] = dct_p[cov_ind] 246 + # in case k = n = 1, Westfeld's implementation uses F4 for embedding.
  247 + f4 = F4(key=self.key)
  248 + return f4._raw_embed(cov_data, hid_data)
  249 +
  250 + hid_data = bytes2bits(hid_data)
  251 + if len(hid_data) % k != 0:
  252 + hid_data = list(hid_data) + [0 for x in range(k - len(hid_data) % k)]
  253 +
  254 + ind_nonzero = np.nonzero(cov_data)[0]
  255 +
  256 + if np.size(ind_nonzero) * k < len(hid_data) * n:
  257 + raise Exception("Supposed secret data too large for stego image.")
  258 +
  259 + ind_cov = 0
  260 + for ind_hid in range(0, len(hid_data), k):
  261 + msg_chunk = hid_data[ind_hid:ind_hid + k]
  262 + cov_chunk = ind_nonzero[ind_cov:ind_cov + n]
  263 + ind_cov += n
264 264
265 success = False 265 success = False
266 - while not success: # loop necessary because of shrinkage 266 + while not success:
267 h = 0 267 h = 0
268 for i in xrange(n): 268 for i in xrange(n):
269 h ^= ((cov_data[cov_chunk[i]] & 1) * (i + 1)) 269 h ^= ((cov_data[cov_chunk[i]] & 1) * (i + 1))
270 scalar_x = 0 270 scalar_x = 0
271 for i in xrange(k): 271 for i in xrange(k):
272 - scalar_x = (scalar_x << 1) + msg_chunk[i] 272 + scalar_x = (scalar_x << 1) + msg_chunk[
  273 + i] # N.B. hid_data[0]:high (that is x2), hid_data[1]:low (that is x1)
273 s = scalar_x ^ h 274 s = scalar_x ^ h
274 if s != 0: 275 if s != 0:
275 self._embed_fun(cov_data, cov_chunk[s - 1]) 276 self._embed_fun(cov_data, cov_chunk[s - 1])
276 else: 277 else:
277 break 278 break
278 279
279 - if cov_data[cov_chunk[s - 1]] == 0: # test for shrinkage  
280 - cov_chunk[s - 1:-1] = cov_chunk[s:] # adjusting  
281 - cov_ind += 1  
282 - while cov_data[dct_p[cov_ind]] == 0 or \  
283 - dct_p[cov_ind] % 64 == 0:  
284 - cov_ind += 1  
285 - cov_chunk[n - 1] = dct_p[cov_ind] 280 + if cov_data[cov_chunk[s - 1]] == 0: # shrinkage
  281 + cov_chunk[s - 1:-1] = cov_chunk[s:]
  282 + cov_chunk[-1] = ind_nonzero[ind_cov]
  283 + ind_cov += 1
286 else: 284 else:
287 success = True 285 success = True
288 286
289 - remaining_bits -= k  
290 -  
291 - self.k_coeff = -1 # prevent k being read from this instance  
292 - return cov_data 287 + return cov_data, ind_hid + k
293 288
294 - def _raw_extract(self, num_bits): 289 + def _raw_extract(self, steg_data, num_bits):
295 k = self.k_coeff 290 k = self.k_coeff
296 n = (1 << k) - 1 291 n = (1 << k) - 1
297 - if self.is_header == None:  
298 - self.is_header = True  
299 - if n == 1 and self.default_embedding:  
300 - f4 = F4(self.ui, self.core)  
301 - f4.seed = self.seed  
302 - f4.dct_p = self.dct_p  
303 - f4.steg_data = self.steg_data  
304 - f4.is_header = self.is_header  
305 - f4.steg_ind = self.steg_ind  
306 - hid_data = f4._raw_extract(num_bits)  
307 - self.steg_ind = f4.steg_ind  
308 - self.is_header = False  
309 - return hid_data  
310 - remaining_bits = num_bits  
311 - hid_data = np.zeros(num_bits, np.uint8)  
312 - hid_ind = 0  
313 -  
314 - dct_p = self.dct_p  
315 -  
316 - is_header = False # signals whether or not extracting header  
317 -  
318 - if self.excess_bits != None:  
319 - hid_data[hid_ind:hid_ind + self.excess_bits.size] = \  
320 - self.excess_bits  
321 - hid_ind += self.excess_bits.size  
322 - remaining_bits -= self.excess_bits.size  
323 -  
324 - curr_chunk = np.zeros(k, np.uint8)  
325 -  
326 - update_cnt = int(num_bits / (100.0 * k))  
327 -  
328 - while remaining_bits > 0:  
329 292
330 - if update_cnt == 0 and not is_header:  
331 - self._set_progress(int(((float(num_bits) \  
332 - - remaining_bits) / num_bits) * 100))  
333 - update_cnt = int(num_bits / (100.0 * k)) 293 + if n == 1 and self.default_embedding:
  294 + f4 = F4(key=self.key)
  295 + return f4._raw_extract(steg_data, num_bits)
334 296
335 - update_cnt -= 1 297 + num_bits_ceil = num_bits
  298 + if num_bits % k != 0:
  299 + num_bits_ceil = k * (num_bits / k + 1)
336 300
337 - steg_chunk = [0 for i in xrange(n)]  
338 - for i in xrange(n):  
339 - self.steg_ind += 1  
340 - while self.steg_data[dct_p[self.steg_ind]] == 0 or \  
341 - dct_p[self.steg_ind] % 64 == 0:  
342 - self.steg_ind += 1  
343 - steg_chunk[i] = self.steg_data[dct_p[self.steg_ind]] 301 + hid_data = np.zeros(num_bits_ceil, np.uint8)
  302 + curr_chunk = np.zeros(k, np.uint8)
  303 + steg_data = steg_data[np.nonzero(steg_data)]
  304 + ind_hid = 0
  305 + for ind_cov in range(0, len(steg_data), n):
  306 + steg_chunk = steg_data[ind_cov:ind_cov + n]
344 307
345 h = 0 # hash value 308 h = 0 # hash value
346 for i in xrange(n): 309 for i in xrange(n):
347 h ^= ((steg_chunk[i] & 1) * (i + 1)) 310 h ^= ((steg_chunk[i] & 1) * (i + 1))
348 311
349 for i in xrange(k): 312 for i in xrange(k):
350 - curr_chunk[k - i - 1] = h % 2  
351 - h /= 2  
352 -  
353 - l = min(k, remaining_bits)  
354 - for i in xrange(l):  
355 - hid_data[hid_ind] = curr_chunk[i]  
356 - hid_ind += 1 313 + curr_chunk[k - i - 1] = h & 1 # N.B. hid_data[0]:high (that is x2), hid_data[1]:low (that is x1)
  314 + h >>= 1
357 315
358 - # save excess bits (for later calls)  
359 - if k > remaining_bits:  
360 - self.excess_bits = curr_chunk[remaining_bits:]  
361 - else:  
362 - self.excess_bits = None 316 + hid_data[ind_hid:ind_hid + k] = curr_chunk[0:k]
  317 + ind_hid += k
363 318
364 - remaining_bits -= k 319 + if ind_hid >= num_bits_ceil: break
365 320
366 - self.is_header = False  
367 - return hid_data 321 + return hid_data, num_bits_ceil
368 322
369 def __str__(self): 323 def __str__(self):
370 return 'F5' 324 return 'F5'
msteg/steganography/F5.pyc
No preview for this file type
msteg/steganography/LSB.pyc
No preview for this file type
res/steged.jpg

47.5 KB | W: | H:

47.9 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
@@ -17,7 +17,9 @@ sample = [[7, 12, 14, -12, 1, 0, -1, 0], @@ -17,7 +17,9 @@ sample = [[7, 12, 14, -12, 1, 0, -1, 0],
17 [0, 0, 0, 0, 0, 0, 0, 0], 17 [0, 0, 0, 0, 0, 0, 0, 0],
18 [0, 0, 0, 0, 0, 0, 0, 0]] 18 [0, 0, 0, 0, 0, 0, 0, 0]]
19 19
20 -sample_key = [46812L, 20559L, 31360L, 16681L, 27536L, 39553L, 5427L, 63029L, 56572L, 36476L, 25695L, 61908L, 63014L, 5908L, 59816L, 56765L] 20 +sample_key = [46812L, 20559L, 31360L, 16681L, 27536L, 39553L, 5427L, 63029L, 56572L, 36476L, 25695L, 61908L, 63014L,
  21 + 5908L, 59816L, 56765L]
  22 +
21 23
22 def diffblock(c1, c2): 24 def diffblock(c1, c2):
23 diff = False 25 diff = False
@@ -32,6 +34,7 @@ def diffblock(c1, c2): @@ -32,6 +34,7 @@ def diffblock(c1, c2):
32 34
33 def diffblocks(a, b): 35 def diffblocks(a, b):
34 diff = False 36 diff = False
  37 + cnt = 0
35 for comp in range(a.image_components): 38 for comp in range(a.image_components):
36 xmax, ymax = a.Jgetcompdim(comp) 39 xmax, ymax = a.Jgetcompdim(comp)
37 for y in range(ymax): 40 for y in range(ymax):
@@ -39,7 +42,8 @@ def diffblocks(a, b): @@ -39,7 +42,8 @@ def diffblocks(a, b):
39 if a.Jgetblock(x, y, comp) != b.Jgetblock(x, y, comp): 42 if a.Jgetblock(x, y, comp) != b.Jgetblock(x, y, comp):
40 print("blocks({},{}) in component {} not match".format(y, x, comp)) 43 print("blocks({},{}) in component {} not match".format(y, x, comp))
41 diff = True 44 diff = True
42 - return diff 45 + cnt += 1
  46 + return diff, cnt
43 47
44 48
45 def test_setblocks(): 49 def test_setblocks():
@@ -131,17 +135,18 @@ def test_rawfile(): @@ -131,17 +135,18 @@ def test_rawfile():
131 raw[i] = raw_size % 256 135 raw[i] = raw_size % 256
132 raw_size /= 256 136 raw_size /= 256
133 raw = np.array(raw) 137 raw = np.array(raw)
134 - print raw.shape,raw 138 + print raw.shape, raw
135 # print raw.size 139 # print raw.size
136 # print bytes2bits(raw) 140 # print bytes2bits(raw)
137 141
  142 +
138 def test_bitbyte(): 143 def test_bitbyte():
139 timer.mark() 144 timer.mark()
140 raw = np.fromfile("res/test4.jpg", np.uint8) 145 raw = np.fromfile("res/test4.jpg", np.uint8)
141 timer.report() 146 timer.report()
142 print raw 147 print raw
143 148
144 - bitsraw = bytes2bits(raw) 149 + bitsraw = bytes2bits(raw)
145 # bitsraw = bitsraw[:24] 150 # bitsraw = bitsraw[:24]
146 timer.report() 151 timer.report()
147 print bitsraw 152 print bitsraw
@@ -150,6 +155,7 @@ def test_bitbyte(): @@ -150,6 +155,7 @@ def test_bitbyte():
150 timer.report() 155 timer.report()
151 print bytesraw 156 print bytesraw
152 157
  158 +
153 def test_iter(): 159 def test_iter():
154 imb = jpegObj.Jpeg("res/test4.jpg") 160 imb = jpegObj.Jpeg("res/test4.jpg")
155 blocks = imb.getCoefBlocks(channel='Y') 161 blocks = imb.getCoefBlocks(channel='Y')
@@ -186,12 +192,12 @@ if __name__ == &#39;__main__&#39;: @@ -186,12 +192,12 @@ if __name__ == &#39;__main__&#39;:
186 192
187 # test_bitbyte() 193 # test_bitbyte()
188 194
189 - ima = jpegObj.Jpeg("res/test3.jpg",key=sample_key) 195 + ima = jpegObj.Jpeg("res/test3.jpg", key=sample_key)
190 # imb = jpegObj.Jpeg("res/new.jpg",key=sample_key) 196 # imb = jpegObj.Jpeg("res/new.jpg",key=sample_key)
191 - imc = jpegObj.Jpeg("res/steged.jpg",key=sample_key) 197 + imc = jpegObj.Jpeg("res/steged.jpg", key=sample_key)
192 print ima.Jgetcompdim(0) 198 print ima.Jgetcompdim(0)
193 - print ima.getkey(),imc.getkey()  
194 - diffblocks(ima, imc) 199 + print ima.getkey(), imc.getkey()
  200 + print diffblocks(ima, imc)
195 201
196 # c1 = ima.getCoefBlocks() 202 # c1 = ima.getCoefBlocks()
197 # c2 = imb.getCoefBlocks() 203 # c2 = imb.getCoefBlocks()
@@ -7,7 +7,7 @@ import pylab as plt @@ -7,7 +7,7 @@ import pylab as plt
7 import mjpeg 7 import mjpeg
8 import mjsteg 8 import mjsteg
9 import jpegObj 9 import jpegObj
10 -from msteg.steganography import F3, F4, LSB 10 +from msteg.steganography import LSB, F3, F4, F5
11 from common import * 11 from common import *
12 12
13 13
@@ -22,13 +22,17 @@ sample = [[7, 12, 14, -12, 1, 0, -1, 0], @@ -22,13 +22,17 @@ sample = [[7, 12, 14, -12, 1, 0, -1, 0],
22 [0, 0, 0, 0, 0, 0, 0, 0], 22 [0, 0, 0, 0, 0, 0, 0, 0],
23 [0, 0, 0, 0, 0, 0, 0, 0]] 23 [0, 0, 0, 0, 0, 0, 0, 0]]
24 24
25 -sample_key = [46812L, 20559L, 31360L, 16681L, 27536L, 39553L, 5427L, 63029L, 56572L, 36476L, 25695L, 61908L, 63014L, 5908L, 59816L, 56765L] 25 +sample_key = [46812L, 20559L, 31360L, 16681L, 27536L, 39553L, 5427L, 63029L, 56572L, 36476L, 25695L, 61908L, 63014L,
  26 + 5908L, 59816L, 56765L]
26 27
27 txtsample = [116, 104, 105, 115, 32, 105, 115, 32, 116, 111, 32, 98, 101, 32, 101, 109, 98, 101, 100, 101, 100, 46, 10] 28 txtsample = [116, 104, 105, 115, 32, 105, 115, 32, 116, 111, 32, 98, 101, 32, 101, 109, 98, 101, 100, 101, 100, 46, 10]
28 29
29 if __name__ == '__main__': 30 if __name__ == '__main__':
30 - f3test = F4.F4() 31 + # f3test = F4.F4(sample_key)
  32 + f3test = F5.F5(sample_key, 3)
31 f3test.embed_raw_data("res/test3.jpg", "res/embeded", "res/steged.jpg") 33 f3test.embed_raw_data("res/test3.jpg", "res/embeded", "res/steged.jpg")
  34 +
  35 + # f3test2 = F4.F4(sample_key)
32 f3test.extract_raw_data("res/steged.jpg", "res/extracted") 36 f3test.extract_raw_data("res/steged.jpg", "res/extracted")
33 print f3test.get_key() 37 print f3test.get_key()
34 pass 38 pass