added a shift parameter for the lsbset module.

This commit is contained in:
Cédric Bonhomme 2018-12-18 21:38:25 +01:00
parent a86361dd27
commit ea2de8142c
No known key found for this signature in database
GPG key ID: A1CB94DE57B7A70D
6 changed files with 47 additions and 15 deletions

View file

@ -1,6 +1,11 @@
Release History
===============
0.9.0 (2018-12-18)
------------------
* added the possibility to shift the encoded bits when using the lsbset module.
0.8.6 (2018-11-05)
------------------

View file

@ -55,6 +55,8 @@ parser_hide.add_argument("-g", "--generator", dest="generator_function",
choices=[generator[0] for generator in \
inspect.getmembers(generators, inspect.isfunction)],
required=True, help="Generator")
parser_hide.add_argument("-s", "--shift", dest="shift",
default=0, help="Shift for the generator")
group_secret = parser_hide.add_mutually_exclusive_group(required=True)
# Non binary secret message to hide
@ -81,6 +83,8 @@ parser_reveal.add_argument("-g", "--generator", dest="generator_function",
choices=[generator[0] for generator in \
inspect.getmembers(generators, inspect.isfunction)],
required=True, help="Generator")
parser_reveal.add_argument("-s", "--shift", dest="shift",
default=0, help="Shift for the generator")
parser_reveal.add_argument("-o", dest="secret_binary",
help="Output for the binary secret (Text or any binary file).")
@ -111,7 +115,8 @@ if arguments.command == 'hide':
elif arguments.secret_file != "":
secret = tools.binary2base64(arguments.secret_file)
img_encoded = lsbset.hide(arguments.input_image_file, secret, generator)
img_encoded = lsbset.hide(arguments.input_image_file, secret, generator,
int(arguments.shift))
try:
img_encoded.save(arguments.output_image_file)
except Exception as e:
@ -120,7 +125,8 @@ if arguments.command == 'hide':
elif arguments.command == 'reveal':
try:
secret = lsbset.reveal(arguments.input_image_file, generator)
secret = lsbset.reveal(arguments.input_image_file, generator,
int(arguments.shift))
except IndexError:
print("Impossible to detect message.")
exit(0)

View file

@ -33,7 +33,7 @@ with codecs.open(os.path.join(here, 'CHANGELOG.rst'), encoding='utf-8') as f:
setup(
name='Stegano',
version='0.8.6',
version='0.9.0',
author='Cédric Bonhomme',
author_email='cedric@cedricbonhomme.org',
packages=packages,

View file

@ -2,7 +2,7 @@
#-*- coding: utf-8 -*-
# Stéganô - Stéganô is a basic Python Steganography module.
# Copyright (C) 2010-2017 Cédric Bonhomme - https://www.cedricbonhomme.org
# Copyright (C) 2010-2018 Cédric Bonhomme - https://www.cedricbonhomme.org
#
# For more information : https://github.com/cedricbonhomme/Stegano
#
@ -20,9 +20,9 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>
__author__ = "Cedric Bonhomme"
__version__ = "$Revision: 0.5 $"
__version__ = "$Revision: 0.6 $"
__date__ = "$Date: 2016/03/13 $"
__revision__ = "$Date: 2017/05/04 $"
__revision__ = "$Date: 2018/12/18 $"
__license__ = "GPLv3"
import sys
@ -36,6 +36,7 @@ from . import generators
def hide(input_image: Union[str, IO[bytes]],
message: str,
generator: Iterator[int],
shift: int = 0,
encoding: str = 'UTF-8',
auto_convert_rgb: bool = False):
"""Hide a message (string) in an image with the
@ -68,6 +69,9 @@ def hide(input_image: Union[str, IO[bytes]],
if len_message_bits > npixels * 3:
raise Exception("The message you want to hide is too long: {}". \
format(message_length))
while shift != 0:
next(generator)
shift -= 1
while index + 3 <= len_message_bits :
generated_number = next(generator)
@ -97,6 +101,7 @@ def hide(input_image: Union[str, IO[bytes]],
def reveal(input_image: Union[str, IO[bytes]],
generator: Iterator[int],
shift: int = 0,
encoding: str = 'UTF-8'):
"""Find a message in an image (with the LSB technique).
"""
@ -107,6 +112,10 @@ def reveal(input_image: Union[str, IO[bytes]],
bitab = []
limit = None
while shift != 0:
next(generator)
shift -= 1
while True:
generated_number = next(generator)
# color = [r, g, b]

View file

@ -54,20 +54,20 @@ class TestLSB(unittest.TestCase):
def test_hide_and_reveal_UTF32LE(self):
messages_to_hide = 'I love 🍕 and 🍫!'
secret = lsb.hide("./tests/sample-files/Lenna.png",
messages_to_hide, 'UTF-32LE')
messages_to_hide, encoding='UTF-32LE')
secret.save("./image.png")
clear_message = lsb.reveal("./image.png", 'UTF-32LE')
clear_message = lsb.reveal("./image.png", encoding='UTF-32LE')
self.assertEqual(messages_to_hide, clear_message)
def test_with_transparent_png(self):
messages_to_hide = ['🍕', 'a', 'foo', 'Hello World!', ':Python:']
for message in messages_to_hide:
secret = lsb.hide("./tests/sample-files/transparent.png",
message, 'UTF-32LE')
message, encoding='UTF-32LE')
secret.save("./image.png")
clear_message = lsb.reveal("./image.png", 'UTF-32LE')
clear_message = lsb.reveal("./image.png", encoding='UTF-32LE')
self.assertEqual(message, clear_message)
@ -75,19 +75,19 @@ class TestLSB(unittest.TestCase):
def test_manual_convert_rgb(self, input):
message_to_hide = 'I love 🍕 and 🍫!'
secret = lsb.hide("./tests/sample-files/Lenna-grayscale.png",
message_to_hide, 'UTF-32LE')
message_to_hide, encoding='UTF-32LE')
@patch('builtins.input', return_value='n')
def test_refuse_convert_rgb(self, input):
message_to_hide = 'I love 🍕 and 🍫!'
with self.assertRaises(Exception):
secret = lsb.hide("./tests/sample-files/Lenna-grayscale.png",
message_to_hide, 'UTF-32LE')
message_to_hide, encoding='UTF-32LE')
def test_auto_convert_rgb(self):
message_to_hide = 'I love 🍕 and 🍫!'
secret = lsb.hide("./tests/sample-files/Lenna-grayscale.png",
message_to_hide, 'UTF-32LE', True)
message_to_hide, encoding='UTF-32LE', auto_convert_rgb=True)
def test_with_text_file(self):
text_file_to_hide = './tests/sample-files/lorem_ipsum.txt'

View file

@ -53,17 +53,29 @@ class TestLSBSet(unittest.TestCase):
generators.eratosthenes())
self.assertEqual(message, clear_message)
def test_hide_and_reveal_with_shift(self):
messages_to_hide = ["a", "foo", "Hello World!", ":Python:"]
for message in messages_to_hide:
secret = lsbset.hide("./tests/sample-files/Lenna.png", message,
generators.eratosthenes(), 4)
secret.save("./image.png")
clear_message = lsbset.reveal("./image.png",
generators.eratosthenes(), 4)
self.assertEqual(message, clear_message)
def test_hide_and_reveal_UTF32LE(self):
messages_to_hide = 'I love 🍕 and 🍫!'
secret = lsbset.hide("./tests/sample-files/Lenna.png",
messages_to_hide,
generators.eratosthenes(),
'UTF-32LE')
encoding='UTF-32LE')
secret.save("./image.png")
clear_message = lsbset.reveal("./image.png", generators.eratosthenes(),
'UTF-32LE')
encoding='UTF-32LE')
self.assertEqual(messages_to_hide, clear_message)
def test_with_transparent_png(self):