From d160c4f1cf42cc3482705b07dfa49fa32781a7df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Bonhomme?= Date: Fri, 20 Dec 2019 00:17:10 +0100 Subject: [PATCH] redoing cli --- bin/__init__.py | 1 + bin/lsb.py | 106 +++++++++++++++++++++++++++ bin/lsbset.py | 170 ++++++++++++++++++++++++++++++++++++++++++++ bin/stegano-lsb-set | 168 ------------------------------------------- pyproject.toml | 3 +- 5 files changed, 279 insertions(+), 169 deletions(-) create mode 100644 bin/__init__.py create mode 100755 bin/lsb.py create mode 100755 bin/lsbset.py delete mode 100755 bin/stegano-lsb-set diff --git a/bin/__init__.py b/bin/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/bin/__init__.py @@ -0,0 +1 @@ + diff --git a/bin/lsb.py b/bin/lsb.py new file mode 100755 index 0000000..9963757 --- /dev/null +++ b/bin/lsb.py @@ -0,0 +1,106 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Stegano - Stegano is a pure Python steganography module. +# Copyright (C) 2010-2019 Cédric Bonhomme - https://www.cedricbonhomme.org +# +# For more information : https://github.com/cedricbonhomme/Stegano +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see + +__author__ = "Cedric Bonhomme" +__version__ = "$Revision: 0.8 $" +__date__ = "$Date: 2016/08/04 $" +__revision__ = "$Date: 2019/06/01 $" +__license__ = "GPLv3" + +import argparse + +try: + from stegano import lsb +except: + print("Install Stegano: pipx install Stegano") + +from stegano import tools + +def main(): + parser = argparse.ArgumentParser(prog='stegano-lsb') + subparsers = parser.add_subparsers(help='sub-command help', dest='command') + + # Subparser: Hide + parser_hide = subparsers.add_parser('hide', help='hide help') + # Original image + parser_hide.add_argument("-i", "--input", dest="input_image_file", + required=True, help="Input image file.") + parser_hide.add_argument("-e", "--encoding", dest="encoding", + choices=tools.ENCODINGS.keys(), default='UTF-8', + help="Specify the encoding of the message to hide." + + " UTF-8 (default) or UTF-32LE.") + + group_secret = parser_hide.add_mutually_exclusive_group(required=True) + # Non binary secret message to hide + group_secret.add_argument("-m", dest="secret_message", + help="Your secret message to hide (non binary).") + # Binary secret message to hide + group_secret.add_argument("-f", dest="secret_file", + help="Your secret to hide (Text or any binary file).") + + # Image containing the secret + parser_hide.add_argument("-o", "--output", dest="output_image_file", + required=True, help="Output image containing the secret.") + + # Shift the message to hide + parser_hide.add_argument("-s", "--shift", dest="shift", default=0, + help="Shift for the message to hide") + + # Subparser: Reveal + parser_reveal = subparsers.add_parser('reveal', help='reveal help') + parser_reveal.add_argument("-i", "--input", dest="input_image_file", + required=True, help="Input image file.") + parser_reveal.add_argument("-e", "--encoding", dest="encoding", + choices=tools.ENCODINGS.keys(), default='UTF-8', + help="Specify the encoding of the message to reveal." + + " UTF-8 (default) or UTF-32LE.") + parser_reveal.add_argument("-o", dest="secret_binary", + help="Output for the binary secret (Text or any binary file).") + # Shift the message to reveal + parser_reveal.add_argument("-s", "--shift", dest="shift", default=0, + help="Shift for the reveal") + + arguments = parser.parse_args() + + + if arguments.command == 'hide': + if arguments.secret_message != None: + secret = arguments.secret_message + elif arguments.secret_file != None: + secret = tools.binary2base64(arguments.secret_file) + + img_encoded = lsb.hide(arguments.input_image_file, secret, + arguments.encoding, int(arguments.shift)) + try: + img_encoded.save(arguments.output_image_file) + except Exception as e: + # If hide() returns an error (Too long message). + print(e) + + elif arguments.command == 'reveal': + secret = lsb.reveal(arguments.input_image_file, arguments.encoding, + int(arguments.shift)) + if arguments.secret_binary != None: + data = tools.base642binary(secret) + with open(arguments.secret_binary, "wb") as f: + f.write(data) + else: + print(secret) diff --git a/bin/lsbset.py b/bin/lsbset.py new file mode 100755 index 0000000..3f04a5f --- /dev/null +++ b/bin/lsbset.py @@ -0,0 +1,170 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Stegano - Stegano is a pure Python steganography module. +# Copyright (C) 2010-2019 Cédric Bonhomme - https://www.cedricbonhomme.org +# +# For more information : https://github.com/cedricbonhomme/Stegano +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see + +__author__ = "Cedric Bonhomme" +__version__ = "$Revision: 0.7 $" +__date__ = "$Date: 2016/03/18 $" +__revision__ = "$Date: 2019/06/04 $" +__license__ = "GPLv3" + +import inspect +import crayons + +try: + from stegano import lsbset + from stegano.lsbset import generators +except: + print("Install stegano: pipx install Stegano") + +from stegano import tools + +import argparse + + + +class ValidateGenerator(argparse.Action): + def __call__(self, parser, args, values, option_string=None): + valid_generators = [generator[0] for generator in inspect.getmembers( + generators, inspect.isfunction)] + # Verify that the generator is valid + generator = values[0] + if generator not in valid_generators: + raise ValueError("Unknown generator: %s" % generator) + # Set the generator_function arg of the parser + setattr(args, self.dest, values) + +def main(): + parser = argparse.ArgumentParser(prog='stegano-lsb-set') + subparsers = parser.add_subparsers(help='sub-command help', dest='command') + + # Subparser: Hide + parser_hide = subparsers.add_parser('hide', help='hide help') + # Original image + parser_hide.add_argument("-i", "--input", dest="input_image_file", + required=True, help="Input image file.") + parser_hide.add_argument("-e", "--encoding", dest="encoding", + choices=tools.ENCODINGS.keys(), default='UTF-8', + help="Specify the encoding of the message to hide." + + " UTF-8 (default) or UTF-32LE.") + + # Generator + parser_hide.add_argument("-g", "--generator", dest="generator_function", + action=ValidateGenerator, + nargs='*', required=True, help="Generator (with optional arguments)") + 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 + group_secret.add_argument("-m", dest="secret_message", + help="Your secret message to hide (non binary).") + # Binary secret message to hide + group_secret.add_argument("-f", dest="secret_file", + help="Your secret to hide (Text or any binary file).") + + # Image containing the secret + parser_hide.add_argument("-o", "--output", dest="output_image_file", + required=True, help="Output image containing the secret.") + + + # Subparser: Reveal + parser_reveal = subparsers.add_parser('reveal', help='reveal help') + parser_reveal.add_argument("-i", "--input", dest="input_image_file", + required=True, help="Input image file.") + parser_reveal.add_argument("-e", "--encoding", dest="encoding", + choices=tools.ENCODINGS.keys(), default='UTF-8', + help="Specify the encoding of the message to reveal." + + " UTF-8 (default) or UTF-32LE.") + parser_reveal.add_argument("-g", "--generator", dest="generator_function", + action=ValidateGenerator, + nargs='*', required=True, help="Generator (with optional arguments)") + 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).") + + + # Subparser: List generators + parser_list_generators = subparsers.add_parser('list-generators', + help='list-generators help') + + arguments = parser.parse_args() + + if arguments.command != 'list-generators': + try: + arguments.generator_function[0] + except AttributeError: + print('You must specify the name of a generator.') + parser.print_help() + exit(1) + + try: + if (arguments.generator_function[0] == "LFSR"): + # Compute the size of the image for use by the LFSR generator if needed + tmp = tools.open_image(arguments.input_image_file) + size = tmp.width * tmp.height + tmp.close() + arguments.generator_function.append(size) + if (len(arguments.generator_function) > 1): + generator = getattr(generators, arguments.generator_function[0])( + *[int(e) for e in arguments.generator_function[1:]]) + else: + generator = getattr(generators, arguments.generator_function[0])() + + except AttributeError as e: + print("Unknown generator: {}".format(arguments.generator_function)) + exit(1) + + if arguments.command == 'hide': + if arguments.secret_message != None: + secret = arguments.secret_message + elif arguments.secret_file != "": + secret = tools.binary2base64(arguments.secret_file) + + 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: + # If hide() returns an error (Too long message). + print(e) + + elif arguments.command == 'reveal': + try: + secret = lsbset.reveal(arguments.input_image_file, generator, + int(arguments.shift)) + except IndexError: + print("Impossible to detect message.") + exit(0) + if arguments.secret_binary != None: + data = tools.base642binary(secret) + with open(arguments.secret_binary, "w") as f: + f.write(data) + else: + print(secret) + + elif arguments.command == 'list-generators': + all_generators = inspect.getmembers(generators, inspect.isfunction) + for generator in all_generators: + print('Generator id:') + print(' {}'.format(crayons.green(generator[0], bold=True))) + print('Desciption:') + print(' {}'.format(generator[1].__doc__)) diff --git a/bin/stegano-lsb-set b/bin/stegano-lsb-set deleted file mode 100755 index faf2c30..0000000 --- a/bin/stegano-lsb-set +++ /dev/null @@ -1,168 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# Stegano - Stegano is a pure Python steganography module. -# Copyright (C) 2010-2019 Cédric Bonhomme - https://www.cedricbonhomme.org -# -# For more information : https://github.com/cedricbonhomme/Stegano -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see - -__author__ = "Cedric Bonhomme" -__version__ = "$Revision: 0.7 $" -__date__ = "$Date: 2016/03/18 $" -__revision__ = "$Date: 2019/06/04 $" -__license__ = "GPLv3" - -import inspect -import crayons - -try: - from stegano import lsbset - from stegano.lsbset import generators -except: - print("Install stegano: pipx install Stegano") - -from stegano import tools - -import argparse -parser = argparse.ArgumentParser(prog='stegano-lsb-set') -subparsers = parser.add_subparsers(help='sub-command help', dest='command') - - -class ValidateGenerator(argparse.Action): - def __call__(self, parser, args, values, option_string=None): - valid_generators = [generator[0] for generator in inspect.getmembers( - generators, inspect.isfunction)] - # Verify that the generator is valid - generator = values[0] - if generator not in valid_generators: - raise ValueError("Unknown generator: %s" % generator) - # Set the generator_function arg of the parser - setattr(args, self.dest, values) - - -# Subparser: Hide -parser_hide = subparsers.add_parser('hide', help='hide help') -# Original image -parser_hide.add_argument("-i", "--input", dest="input_image_file", - required=True, help="Input image file.") -parser_hide.add_argument("-e", "--encoding", dest="encoding", - choices=tools.ENCODINGS.keys(), default='UTF-8', - help="Specify the encoding of the message to hide." + - " UTF-8 (default) or UTF-32LE.") - -# Generator -parser_hide.add_argument("-g", "--generator", dest="generator_function", - action=ValidateGenerator, - nargs='*', required=True, help="Generator (with optional arguments)") -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 -group_secret.add_argument("-m", dest="secret_message", - help="Your secret message to hide (non binary).") -# Binary secret message to hide -group_secret.add_argument("-f", dest="secret_file", - help="Your secret to hide (Text or any binary file).") - -# Image containing the secret -parser_hide.add_argument("-o", "--output", dest="output_image_file", - required=True, help="Output image containing the secret.") - - -# Subparser: Reveal -parser_reveal = subparsers.add_parser('reveal', help='reveal help') -parser_reveal.add_argument("-i", "--input", dest="input_image_file", - required=True, help="Input image file.") -parser_reveal.add_argument("-e", "--encoding", dest="encoding", - choices=tools.ENCODINGS.keys(), default='UTF-8', - help="Specify the encoding of the message to reveal." + - " UTF-8 (default) or UTF-32LE.") -parser_reveal.add_argument("-g", "--generator", dest="generator_function", - action=ValidateGenerator, - nargs='*', required=True, help="Generator (with optional arguments)") -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).") - - -# Subparser: List generators -parser_list_generators = subparsers.add_parser('list-generators', - help='list-generators help') - -arguments = parser.parse_args() - -if arguments.command != 'list-generators': - try: - arguments.generator_function[0] - except AttributeError: - print('You must specify the name of a generator.') - parser.print_help() - exit(1) - - try: - if (arguments.generator_function[0] == "LFSR"): - # Compute the size of the image for use by the LFSR generator if needed - tmp = tools.open_image(arguments.input_image_file) - size = tmp.width * tmp.height - tmp.close() - arguments.generator_function.append(size) - if (len(arguments.generator_function) > 1): - generator = getattr(generators, arguments.generator_function[0])( - *[int(e) for e in arguments.generator_function[1:]]) - else: - generator = getattr(generators, arguments.generator_function[0])() - - except AttributeError as e: - print("Unknown generator: {}".format(arguments.generator_function)) - exit(1) - -if arguments.command == 'hide': - if arguments.secret_message != None: - secret = arguments.secret_message - elif arguments.secret_file != "": - secret = tools.binary2base64(arguments.secret_file) - - 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: - # If hide() returns an error (Too long message). - print(e) - -elif arguments.command == 'reveal': - try: - secret = lsbset.reveal(arguments.input_image_file, generator, - int(arguments.shift)) - except IndexError: - print("Impossible to detect message.") - exit(0) - if arguments.secret_binary != None: - data = tools.base642binary(secret) - with open(arguments.secret_binary, "w") as f: - f.write(data) - else: - print(secret) - -elif arguments.command == 'list-generators': - all_generators = inspect.getmembers(generators, inspect.isfunction) - for generator in all_generators: - print('Generator id:') - print(' {}'.format(crayons.green(generator[0], bold=True))) - print('Desciption:') - print(' {}'.format(generator[1].__doc__)) diff --git a/pyproject.toml b/pyproject.toml index 8b8ad43..098902a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,7 +30,8 @@ include = [ ] [tool.poetry.scripts] -stegano-lsb = "bin:steganolsb" +stegano-lsb = "bin.lsb:main" +stegano-lsb-set = "bin.lsbset:main" # stegano-lsb-set = "bin.stegano-lsb-set" # stegano-red = "bin.stegano-red" # stegano-steganalysis-parity = "bin.stegano-steganalysis-parity"