Commit 6cbb3879dd61c0533550959f17558fdd998e4a79

Authored by Chunk
1 parent 45a82355
Exists in master

F4 updated.

jpegObj/__init__.py
... ... @@ -30,6 +30,8 @@ colorCode = {
30 30 "YCCK": 5
31 31 }
32 32  
  33 +colorParam = ['Y', 'Cb', 'Cr']
  34 +
33 35 # The JPEG class
34 36 # ==============
35 37  
... ... @@ -69,28 +71,35 @@ class Jpeg(Jsteg):
69 71 # 1D Signal Representations
70 72 # -------------------------
71 73  
72   - def rawsignal(self, mask=base.acMaskBlock):
  74 + def rawsignal(self, mask=base.acMaskBlock, channel="All"):
73 75 """
74 76 Return a 1D array of AC coefficients.
75 77 (Most applications should use getsignal() rather than rawsignal().)
76 78 """
77 79 R = []
78   - for X in self.coef_arrays:
  80 + if channel == "All":
  81 + for X in self.coef_arrays:
  82 + (h, w) = X.shape
  83 + A = base.acMask(h, w, mask)
  84 + R = np.hstack([R, X[A]])
  85 + else:
  86 + cID = self.getCompID(channel)
  87 + X = self.coef_arrays[cID]
79 88 (h, w) = X.shape
80 89 A = base.acMask(h, w, mask)
81 90 R = np.hstack([R, X[A]])
82 91 return R
83 92  
84   - def getsignal(self, mask=base.acMaskBlock):
  93 + def getsignal(self, mask=base.acMaskBlock, channel="All"):
85 94 """Return a 1D array of AC coefficients in random order."""
86   - R = self.rawsignal(mask)
  95 + R = self.rawsignal(mask, channel)
87 96 if self.key == None:
88 97 return R
89 98 else:
90 99 rnd.seed(self.key)
91 100 return R[rnd.permutation(len(R))]
92 101  
93   - def setsignal(self, R0, mask=base.acMaskBlock):
  102 + def setsignal(self, R0, mask=base.acMaskBlock, channel="All"):
94 103 """Reinserts AC coefficients from getitem in the correct positions."""
95 104 if self.key != None:
96 105 rnd.seed(self.key)
... ... @@ -100,13 +109,40 @@ class Jpeg(Jsteg):
100 109 R[P] = R0
101 110 else:
102 111 R = R0
103   - for X in self.coef_arrays:
  112 + if channel == "All":
  113 + for cID in range(3):
  114 + X = self.coef_arrays[cID]
  115 + s = X.size * 63 / 64
  116 + (h, w) = X.shape
  117 + X[base.acMask(h, w, mask)] = R[fst:(fst + s)]
  118 + fst += s
  119 +
  120 + # Jset
  121 + blocks = self.getCoefBlocks(channel=colorParam[cID])
  122 + xmax, ymax = self.Jgetcompdim(cID)
  123 + for y in range(ymax):
  124 + for x in range(xmax):
  125 + block = blocks[y, x]
  126 + self.Jsetblock(x, y, cID, bytearray(block.astype(np.int16)))
  127 +
  128 + else:
  129 + cID = self.getCompID(channel)
  130 + X = self.coef_arrays[cID]
104 131 s = X.size * 63 / 64
105 132 (h, w) = X.shape
106 133 X[base.acMask(h, w, mask)] = R[fst:(fst + s)]
107 134 fst += s
  135 +
  136 + # Jset
  137 + blocks = self.getCoefBlocks(channel)
  138 + xmax, ymax = self.Jgetcompdim(cID)
  139 + for y in range(ymax):
  140 + for x in range(xmax):
  141 + block = blocks[y, x]
  142 + self.Jsetblock(x, y, cID, bytearray(block.astype(np.int16)))
  143 +
108 144 assert len(R) == fst
109   - return;
  145 +
110 146  
111 147 # Histogram and Image Statistics
112 148 # ------------------------------
... ... @@ -247,12 +283,12 @@ class Jpeg(Jsteg):
247 283 assert blocks.shape[-2:] == (8, 8), "block is expected of size (8,8)"
248 284 cID = self.getCompID(channel)
249 285  
250   - vmax,hmax = blocks.shape[:2]
  286 + vmax, hmax = blocks.shape[:2]
251 287 for i in range(vmax):
252 288 for j in range(hmax):
253 289 v, h = i * 8, j * 8
254   - self.coef_arrays[cID][v:v + 8, h:h + 8] = blocks[i,j]
255   - self.Jsetblock(j, i, cID, bytearray(blocks[i,j].astype(np.int16)))
  290 + self.coef_arrays[cID][v:v + 8, h:h + 8] = blocks[i, j]
  291 + self.Jsetblock(j, i, cID, bytearray(blocks[i, j].astype(np.int16)))
256 292  
257 293 # Decompression
258 294 # -------------
... ...
jpegObj/__init__.pyc
No preview for this file type
msteg/StegBase.py
1   -"""
2   -This module implements a common base class of the steganographic
3   -algorithms which embed data into JPEG files.
4   -In order to run plugins inheriting from this class
5   -you must build the rw_dct.so library which interfaces with libjpeg.
6   -To do so, just run
7   -% python setup.py build
8   -in stegotool/util and copy the rw_dct.so
9   -library (which can be found somewhere in the build-directory to
10   -stegotool/util.
11   -
12   -"""
  1 +__author__ = 'chunk'
  2 +
  3 +
13 4 import numpy as np
14 5 import time
15 6 import os
... ... @@ -21,6 +12,7 @@ import mjsteg
21 12 import jpegObj
22 13 from common import *
23 14  
  15 +sample_key = [46812L, 20559L, 31360L, 16681L, 27536L, 39553L, 5427L, 63029L, 56572L, 36476L, 25695L, 61908L, 63014L, 5908L, 59816L, 56765L]
24 16  
25 17 class StegBase(object):
26 18 """
... ... @@ -36,12 +28,14 @@ class StegBase(object):
36 28 self.cov_jpeg = None
37 29 self.cov_data = None
38 30 self.hid_data = None
  31 + self.key = None
39 32  
40 33 def _get_cov_data(self, img_path):
41 34 """
42 35 Returns DCT coefficients of the cover image.
43 36 """
44 37 self.cov_jpeg = jpegObj.Jpeg(img_path)
  38 + self.key = self.cov_jpeg.getkey()
45 39 self.cov_data = self.cov_jpeg.getCoefBlocks()
46 40 return self.cov_data
47 41  
... ... @@ -150,7 +144,7 @@ class StegBase(object):
150 144 float(emb_size) / cov_size))
151 145  
152 146 # dummy functions to please pylint
153   - def _raw_embed(self, cov_data, hid_data, status_begin=0):
  147 + def _raw_embed(self, cov_data, hid_data):
154 148 pass
155 149  
156 150 def _raw_extract(self, steg_data, num_bits):
... ...
msteg/StegBase.pyc
No preview for this file type
msteg/steganography/F3.py
1   -"""
2   -<p>This module implements the F3 steganography algorithm invented by
3   -Andreas Westfeld.</p>
4   -
5   -It embeds a secret message in JPEG DCT coefficients.
6   -It differs from simpler algorithms such as JSteg by subtracting the
7   -absolute DCT value if the currently embedded bit and the LSB of the DCT
8   -value are not equal. DCT coefficients with value 0 are ignored.<br />
9   -If a DCT coefficient is equal to 1 or -1 the current bit
10   -is embedded repeatedly in order to make non-ambiguous extraction possible.
11   -"""
  1 +__author__ = 'chunk'
  2 +
  3 +
12 4 import time
13 5 import math
14 6 import numpy as np
... ... @@ -42,7 +34,7 @@ class F3(StegBase):
42 34 lossy compression.
43 35 """
44 36 self.t0 = time.time()
45   - StegBase._post_embed_actions(self, src_cover, src_hidden, tgt_stego)
  37 + self._post_embed_actions(src_cover, src_hidden, tgt_stego)
46 38  
47 39 def extract_raw_data(self, src_steg, tgt_hidden):
48 40 """ This method extracts secret data from a stego image. It is
... ... @@ -53,9 +45,9 @@ class F3(StegBase):
53 45 tgt_hidden - A pathname denoting where the extracted data should be saved to.
54 46 """
55 47 self.t0 = time.time()
56   - StegBase._post_extract_actions(self, src_steg, tgt_hidden)
  48 + self._post_extract_actions(src_steg, tgt_hidden)
57 49  
58   - def _raw_embed(self, cov_data, hid_data, status_begin=0):
  50 + def _raw_embed(self, cov_data, hid_data):
59 51 """
60 52 cov_data - 4-D numpy.int32 array
61 53 hid_data - 1-D numpy.uint8 array
... ...
msteg/steganography/F3.pyc
No preview for this file type
msteg/steganography/F4.py
1   -"""
2   -<p>This module implements a slight variant of the F4 steganography algorithm
3   -invented by Andreas Westfeld. It embeds a secret message in JPEG
4   -DCT coefficients.</p>
5   -It differs from F3 in that even negative and odd positive DCT
6   -coefficients represent a 1 and odd negative and even positive
7   -DCT coefficients represent a 0. It also supports permutative strattling
8   -which is not included in the original description of F4.
9   -"""
  1 +__author__ = 'chunk'
  2 +
10 3 import time
11 4 import numpy as np
12   -from msteg.StegBase import StegBase
  5 +import numpy.random as rnd
  6 +from msteg.StegBase import *
  7 +import mjsteg
  8 +import jpegObj
13 9 from common import *
14 10  
15 11  
... ... @@ -18,51 +14,105 @@ class F4(StegBase):
18 14 with the F3 algorithm and <i>extract_raw_data</i> to extract data
19 15 which was embedded previously. """
20 16  
21   - def __init__(self):
  17 + def __init__(self, key=sample_key):
22 18 """
23 19 Constructor of the F3 class.
24 20 """
25 21 StegBase.__init__(self)
  22 + self.key = key
26 23  
27   - def embed_raw_data(self, src_cover, src_hidden, tgt_stego):
28   - """ This method embeds arbitrary data into a cover image.
29   - The cover image must be a JPEG.
  24 + def _get_cov_data(self, img_path):
  25 + """
  26 + Returns DCT coefficients of the cover image.
  27 + """
  28 + self.cov_jpeg = jpegObj.Jpeg(img_path, key=self.key)
30 29  
31   - src_cover - A valid pathname to an image file which serves as cover image
32   - (the image which the secret image is embedded into).
  30 + cov_data = self.cov_jpeg.getsignal(channel='Y')
  31 + self.cov_data = np.array(cov_data, dtype=np.int16)
  32 + return self.cov_data
33 33  
34   - src_hidden - A valid pathname to an arbitrary file that is supposed to be
35   - embedded into the cover image.
  34 + def embed_raw_data(self, src_cover, src_hidden, tgt_stego):
36 35  
37   - tgt_stego - Target pathname of the resulting stego image. You should save to a
38   - PNG or another lossless format, because many LSBs don't survive
39   - lossy compression.
40   - """
41 36 self.t0 = time.time()
42   - StegBase._post_embed_actions(self, src_cover, src_hidden, tgt_stego)
43 37  
44   - def extract_raw_data(self, src_steg, tgt_hidden):
45   - """ This method extracts secret data from a stego image. It is
46   - (obviously) the inverse operation of embed_raw_data.
  38 + try:
  39 + cov_data = self._get_cov_data(src_cover)
  40 + hid_data = self._get_hid_data(src_hidden)
  41 + # print hid_data.dtype,type(hid_data),hid_data.tolist()
47 42  
48   - src_stego - A valid pathname to an image file which serves as stego image.
  43 + cov_data, bits_cnt = self._raw_embed(cov_data, hid_data)
  44 +
  45 + if bits_cnt != np.size(hid_data) * 8:
  46 + raise Exception("Expected embedded size is %db but actually %db." % (
  47 + np.size(hid_data) * 8, bits_cnt))
  48 +
  49 + self.cov_jpeg.setsignal(cov_data, channel='Y')
  50 + self.cov_jpeg.Jwrite(tgt_stego)
  51 +
  52 + # size_cov = os.path.getsize(tgt_stego)
  53 + size_cov = np.size(cov_data) / 8
  54 + size_embedded = np.size(hid_data)
  55 +
  56 + self._display_stats("embedded", size_cov, size_embedded,
  57 + time.time() - self.t0)
  58 +
  59 + except TypeError as e:
  60 + raise e
  61 + except Exception as expt:
  62 + print "Exception when embedding!"
  63 + raise
  64 +
  65 + def extract_raw_data(self, src_steg, tgt_hidden):
49 66  
50   - tgt_hidden - A pathname denoting where the extracted data should be saved to.
51   - """
52 67 self.t0 = time.time()
53   - StegBase._post_extract_actions(self, src_steg, tgt_hidden)
54 68  
55   - def _raw_embed(self, cov_data, hid_data, status_begin=0):
  69 + try:
  70 + steg_data = self._get_cov_data(src_steg)
  71 + # emb_size = os.path.getsize(src_steg)
  72 + emb_size = np.size(steg_data) / 8
  73 +
  74 +
  75 + # recovering file size
  76 + header_size = 4 * 8
  77 + size_data, bits_cnt = self._raw_extract(steg_data, header_size)
  78 + size_data = bits2bytes(size_data)
  79 + print size_data
  80 +
  81 + size_hd = 0
  82 + for i in xrange(4):
  83 + size_hd += size_data[i] * 256 ** i
  84 +
  85 + raw_size = size_hd * 8
  86 +
  87 + if raw_size > np.size(steg_data):
  88 + raise Exception("Supposed secret data too large for stego image.")
  89 +
  90 + hid_data, bits_cnt = self._raw_extract(steg_data, raw_size)
  91 +
  92 + if bits_cnt != raw_size:
  93 + raise Exception("Expected embedded size is %db but actually %db." % (
  94 + raw_size, bits_cnt))
  95 +
  96 + hid_data = bits2bytes(hid_data)
  97 + # print hid_data.dtype,type(hid_data),hid_data.tolist()
  98 + hid_data[4:].tofile(tgt_hidden)
  99 +
  100 + self._display_stats("extracted", emb_size,
  101 + np.size(hid_data),
  102 + time.time() - self.t0)
  103 + except Exception as expt:
  104 + print "Exception when extracting!"
  105 + raise
  106 +
  107 + def _raw_embed(self, cov_data, hid_data):
56 108 """
57   - cov_data - 4-D numpy.int32 array
  109 + cov_data - 1-D numpy.int16 array (permunated)
58 110 hid_data - 1-D numpy.uint8 array
59 111 """
60 112 hid_data = bytes2bits(hid_data)
61 113 i = 0
62   - cnt = -1
63 114 for x in np.nditer(cov_data, op_flags=['readwrite']):
64   - cnt = cnt + 1
65   - if x == 0 or cnt % 64 == 0: continue
  115 + if x == 0: continue
66 116  
67 117 m = (hid_data[i] & 1)
68 118 if x > 0 and x & 1 != m:
... ... @@ -72,19 +122,17 @@ class F4(StegBase):
72 122 if x == 0: continue
73 123 i += 1
74 124 if i == hid_data.size: break
75   -
76   - return cov_data
  125 + return cov_data, i
77 126  
78 127 def _raw_extract(self, steg_data, num_bits):
79 128 """
80 129 Just a small helper function to extract hidden data.
  130 + steg_data - 1-D numpy.int16 array (permunated)
81 131 """
82 132 hid_data = np.zeros(num_bits, np.uint8)
83 133 j = 0
84   - cnt = -1
85   - for x in np.nditer(steg_data):
86   - cnt = cnt + 1
87   - if x == 0 or cnt % 64 == 0: continue
  134 + for x in steg_data:
  135 + if x == 0: continue
88 136 if j >= num_bits: break
89 137 if x > 0:
90 138 hid_data[j] = x & 1
... ... @@ -93,7 +141,7 @@ class F4(StegBase):
93 141  
94 142 j = j + 1
95 143  
96   - return hid_data
  144 + return hid_data, j
97 145  
98 146 def __str__(self):
99 147 return "F4'"
... ...
msteg/steganography/F4.pyc
No preview for this file type
msteg/steganography/LSB.py
1   -"""
2   -<p>This plugin implements two variants of a well-known steganographic
3   -procedure commonly referred to as LSB algorithm.</p>
4   -The general idea is to
5   -overwrite some portion (usually the k least significant bits) of each byte
6   -in the cover image. The below methods specify the number of overwritten
7   -bits a parameter named word_size. Thus --- in this context --- word means
8   -\"a group of bits of a fixed size\".
9   -"""
  1 +__author__ = 'chunk'
  2 +
  3 +
10 4 import time
11 5 import numpy as np
12 6 import scipy as sp
... ... @@ -53,7 +47,7 @@ class LSB(StegBase):
53 47 self.t0 = time.time()
54 48 StegBase._post_extract_actions(self, src_steg, tgt_hidden)
55 49  
56   - def _raw_embed(self, cov_data, hid_data, status_begin=0):
  50 + def _raw_embed(self, cov_data, hid_data):
57 51 """
58 52 cov_data - 4-D numpy.int32 array
59 53 hid_data - 1-D numpy.uint8 array
... ...
msteg/steganography/LSB.pyc
No preview for this file type
res/steged.jpg

43.7 KB | W: | H:

47.5 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
test_jpeg.py
... ... @@ -3,6 +3,7 @@ __author__ = &#39;chunk&#39;
3 3 import numpy as np
4 4 import mjsteg
5 5 import jpegObj
  6 +from jpegObj import base
6 7 from common import *
7 8  
8 9 timer = Timer()
... ... @@ -16,6 +17,7 @@ sample = [[7, 12, 14, -12, 1, 0, -1, 0],
16 17 [0, 0, 0, 0, 0, 0, 0, 0],
17 18 [0, 0, 0, 0, 0, 0, 0, 0]]
18 19  
  20 +sample_key = [46812L, 20559L, 31360L, 16681L, 27536L, 39553L, 5427L, 63029L, 56572L, 36476L, 25695L, 61908L, 63014L, 5908L, 59816L, 56765L]
19 21  
20 22 def diffblock(c1, c2):
21 23 diff = False
... ... @@ -184,16 +186,28 @@ if __name__ == &#39;__main__&#39;:
184 186  
185 187 # test_bitbyte()
186 188  
187   - ima = jpegObj.Jpeg("res/test3.jpg")
188   - imb = jpegObj.Jpeg("res/steged.jpg")
  189 + ima = jpegObj.Jpeg("res/test3.jpg",key=sample_key)
  190 + imb = jpegObj.Jpeg("res/new.jpg",key=sample_key)
  191 + imc = jpegObj.Jpeg("res/steged.jpg",key=sample_key)
189 192 print ima.Jgetcompdim(0)
190   - diffblocks(ima, imb)
191   -
192   - c1 = ima.getCoefBlocks()
193   - c2 = imb.getCoefBlocks()
194   -
195   - print c1[0],c2[0]
  193 + print ima.getkey(),imb.getkey()
  194 + diffblocks(imb, ima)
196 195  
  196 + # c1 = ima.getCoefBlocks()
  197 + # c2 = imb.getCoefBlocks()
  198 + #
  199 + # # print c1[0],c2[0]
  200 + # s1 = imb.getsignal(channel='Y')
  201 + # s2 = ima.getsignal(channel='Y')
  202 + # imb.setsignal(s2,channel='Y')
  203 + # imb.Jwrite('res/new.jpg')
  204 +
  205 +
  206 + # print base.acMask(8,16)
  207 + # mmask = base.acMaskBlock
  208 + # print mmask
  209 + # sample = np.array(sample)[mmask]
  210 + # print np.hstack([[],sample])
197 211 pass
198 212  
199 213  
... ...
test_steg.py
... ... @@ -22,10 +22,12 @@ sample = [[7, 12, 14, -12, 1, 0, -1, 0],
22 22 [0, 0, 0, 0, 0, 0, 0, 0],
23 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]
  26 +
25 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]
26 28  
27 29 if __name__ == '__main__':
28   - f3test = F3.F3()
  30 + f3test = F4.F4()
29 31 f3test.embed_raw_data("res/test3.jpg", "res/embeded", "res/steged.jpg")
30 32 f3test.extract_raw_data("res/steged.jpg", "res/extracted")
31 33  
... ...