From f6aa2207f45f4d685bfb845e818e80f1f5acd15a Mon Sep 17 00:00:00 2001 From: Flavien Date: Fri, 11 Nov 2022 14:06:48 +0100 Subject: [PATCH] Merge lsb and lsbset bin --- bin/__init__.py | 1 - bin/lsb.py | 123 +++++++++++++++++++++++---- bin/lsbset.py | 218 ------------------------------------------------ pyproject.toml | 1 - 4 files changed, 105 insertions(+), 238 deletions(-) delete mode 100755 bin/lsbset.py diff --git a/bin/__init__.py b/bin/__init__.py index 8b13789..e69de29 100644 --- a/bin/__init__.py +++ b/bin/__init__.py @@ -1 +0,0 @@ - diff --git a/bin/lsb.py b/bin/lsb.py index 1e8d9e7..7dd342c 100755 --- a/bin/lsb.py +++ b/bin/lsb.py @@ -20,20 +20,38 @@ # along with this program. If not, see __author__ = "Cedric Bonhomme" -__version__ = "$Revision: 0.8 $" -__date__ = "$Date: 2016/08/04 $" -__revision__ = "$Date: 2019/06/01 $" +__version__ = "$Revision: 0.7 $" +__date__ = "$Date: 2016/03/18 $" +__revision__ = "$Date: 2019/06/04 $" __license__ = "GPLv3" -import argparse +import inspect +import crayons try: from stegano import lsb + from stegano.lsb import generators except Exception: - print("Install Stegano: pipx install Stegano") + 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") @@ -59,6 +77,22 @@ def main(): + " UTF-8 (default) or UTF-32LE.", ) + # Generator + parser_hide.add_argument( + "-g", + "--generator", + dest="generator_function", + action=ValidateGenerator, + nargs="*", + required=False, + help="Generator (with optional arguments)", + ) + + # Shift the message to hide + 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( @@ -78,11 +112,6 @@ def main(): 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( @@ -101,26 +130,69 @@ def main(): help="Specify the encoding of the message to reveal." + " UTF-8 (default) or UTF-32LE.", ) + + # Generator + parser_reveal.add_argument( + "-g", + "--generator", + dest="generator_function", + action=ValidateGenerator, + nargs="*", + required=False, + help="Generator (with optional arguments)", + ) + + # Shift the message to reveal + 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).", ) - # Shift the message to reveal - parser_reveal.add_argument( - "-s", "--shift", dest="shift", default=0, help="Shift for the reveal" + + # Subparser: List generators + parser_list_generators = subparsers.add_parser( + "list-generators", help="list-generators help" ) arguments = parser.parse_args() + if arguments.command != "list-generators": + if not arguments.generator_function: + generator = None + else: + 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: + print("Unknown generator: {}".format(arguments.generator_function)) + exit(1) + if arguments.command == "hide": if arguments.secret_message is not None: secret = arguments.secret_message - elif arguments.secret_file is not None: + elif arguments.secret_file != "": secret = tools.binary2base64(arguments.secret_file) img_encoded = lsb.hide( - arguments.input_image_file, secret, arguments.encoding, int(arguments.shift) + image=arguments.input_image_file, + message=secret, + generator=generator, + shift=int(arguments.shift), + encoding=arguments.encoding, ) try: img_encoded.save(arguments.output_image_file) @@ -129,12 +201,27 @@ def main(): print(e) elif arguments.command == "reveal": - secret = lsb.reveal( - arguments.input_image_file, arguments.encoding, int(arguments.shift) - ) + try: + secret = lsb.reveal( + encoded_image=arguments.input_image_file, + generator=generator, + shift=int(arguments.shift), + encoding=arguments.encoding, + ) + except IndexError: + print("Impossible to detect message.") + exit(0) if arguments.secret_binary is not None: data = tools.base642binary(secret) with open(arguments.secret_binary, "wb") 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/lsbset.py b/bin/lsbset.py deleted file mode 100755 index 95eb41d..0000000 --- a/bin/lsbset.py +++ /dev/null @@ -1,218 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# Stegano - Stegano is a pure Python steganography module. -# Copyright (C) 2010-2022 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 lsb - from stegano.lsb import generators -except Exception: - 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: - print("Unknown generator: {}".format(arguments.generator_function)) - exit(1) - - if arguments.command == "hide": - if arguments.secret_message is not None: - secret = arguments.secret_message - elif arguments.secret_file != "": - secret = tools.binary2base64(arguments.secret_file) - - img_encoded = lsb.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 = lsb.reveal( - arguments.input_image_file, generator, int(arguments.shift) - ) - except IndexError: - print("Impossible to detect message.") - exit(0) - if arguments.secret_binary is not None: - data = tools.base642binary(secret) - with open(arguments.secret_binary, "wb") 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 859d42d..fc4f6ef 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -38,7 +38,6 @@ include = [ [tool.poetry.scripts] stegano-lsb = "bin.lsb:main" -stegano-lsb-set = "bin.lsbset:main" stegano-red = "bin.red:main" stegano-steganalysis-parity = "bin.parity:main" stegano-steganalysis-statistics = "bin.statistics:main"