Merge lsb and lsbset modules

This commit is contained in:
Flavien 2022-11-11 12:15:25 +01:00
parent 0d98e1834c
commit 3103a3ae9b
7 changed files with 48 additions and 120 deletions

View file

@ -29,8 +29,8 @@ import inspect
import crayons import crayons
try: try:
from stegano import lsbset from stegano import lsb
from stegano.lsbset import generators from stegano.lsb import generators
except Exception: except Exception:
print("Install stegano: pipx install Stegano") print("Install stegano: pipx install Stegano")
@ -185,7 +185,7 @@ def main():
elif arguments.secret_file != "": elif arguments.secret_file != "":
secret = tools.binary2base64(arguments.secret_file) secret = tools.binary2base64(arguments.secret_file)
img_encoded = lsbset.hide( img_encoded = lsb.hide(
arguments.input_image_file, secret, generator, int(arguments.shift) arguments.input_image_file, secret, generator, int(arguments.shift)
) )
try: try:
@ -196,7 +196,7 @@ def main():
elif arguments.command == "reveal": elif arguments.command == "reveal":
try: try:
secret = lsbset.reveal( secret = lsb.reveal(
arguments.input_image_file, generator, int(arguments.shift) arguments.input_image_file, generator, int(arguments.shift)
) )
except IndexError: except IndexError:

View file

@ -4,6 +4,5 @@
from . import red from . import red
from . import exifHeader from . import exifHeader
from . import lsb from . import lsb
from . import lsbset
from . import steganalysis from . import steganalysis

View file

@ -29,7 +29,7 @@ import itertools
import cv2 import cv2
import numpy as np import numpy as np
import math import math
from typing import Dict, Iterator, List, Any, Union from typing import Dict, Iterator, List, Any
def identity() -> Iterator[int]: def identity() -> Iterator[int]:
@ -225,7 +225,7 @@ def LFSR(m: int) -> Iterator[int]:
# Add the feedback bit # Add the feedback bit
state.insert(0, feedback) state.insert(0, feedback)
# Convert the registers to an int # Convert the registers to an int
out = sum([e * (2 ** i) for i, e in enumerate(state)]) out = sum([e * (2**i) for i, e in enumerate(state)])
yield out yield out

64
stegano/lsb/lsb.py Executable file → Normal file
View file

@ -20,55 +20,71 @@
# along with this program. If not, see <http://www.gnu.org/licenses/> # along with this program. If not, see <http://www.gnu.org/licenses/>
__author__ = "Cedric Bonhomme" __author__ = "Cedric Bonhomme"
__version__ = "$Revision: 0.4 $" __version__ = "$Revision: 0.7 $"
__date__ = "$Date: 2016/08/04 $" __date__ = "$Date: 2016/03/13 $"
__revision__ = "$Date: 2019/06/01 $" __revision__ = "$Date: 2019/05/31 $"
__license__ = "GPLv3" __license__ = "GPLv3"
from typing import IO, Union from typing import IO, Iterator, Union
from .generators import identity
from stegano import tools from stegano import tools
def hide( def hide(
image: Union[str, IO[bytes]], image: Union[str, IO[bytes]],
message: str, message: str,
encoding: str = "UTF-8", generator: Iterator[int] = None,
shift: int = 0, shift: int = 0,
encoding: str = "UTF-8",
auto_convert_rgb: bool = False, auto_convert_rgb: bool = False,
): ):
"""Hide a message (string) in an image with the """Hide a message (string) in an image with the
LSB (Least Significant Bit) technique. LSB (Least Significant Bit) technique.
""" """
hider = tools.Hider(image, message, encoding, auto_convert_rgb) hider = tools.Hider(image, message, encoding, auto_convert_rgb)
width, height = hider.encoded_image.size width = hider.encoded_image.width
for row in range(height): if not generator:
for col in range(width): generator = identity()
if shift != 0:
shift -= 1
continue
if hider.encode_another_pixel(): while shift != 0:
hider.encode_pixel((col, row)) next(generator)
else: shift -= 1
return hider.encoded_image
while hider.encode_another_pixel():
generated_number = next(generator)
col = generated_number % width
row = int(generated_number / width)
hider.encode_pixel((col, row))
return hider.encoded_image
def reveal( def reveal(
encoded_image: Union[str, IO[bytes]], encoded_image: Union[str, IO[bytes]],
encoding: str = "UTF-8", generator: Iterator[int] = None,
shift: int = 0, shift: int = 0,
encoding: str = "UTF-8",
): ):
"""Find a message in an image (with the LSB technique).""" """Find a message in an image (with the LSB technique)."""
revealer = tools.Revealer(encoded_image, encoding) revealer = tools.Revealer(encoded_image, encoding)
width, height = revealer.encoded_image.size width = revealer.encoded_image.width
for row in range(height): if not generator:
for col in range(width): generator = identity()
if shift != 0:
shift -= 1
continue
if revealer.decode_pixel((col, row)): while shift != 0:
return revealer.secret_message next(generator)
shift -= 1
while True:
generated_number = next(generator)
col = generated_number % width
row = int(generated_number / width)
if revealer.decode_pixel((col, row)):
return revealer.secret_message

View file

@ -1,4 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from .lsbset import *

View file

@ -1,83 +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://git.sr.ht/~cedric/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 <http://www.gnu.org/licenses/>
__author__ = "Cedric Bonhomme"
__version__ = "$Revision: 0.7 $"
__date__ = "$Date: 2016/03/13 $"
__revision__ = "$Date: 2019/05/31 $"
__license__ = "GPLv3"
from typing import IO, Iterator, Union
from stegano import tools
def hide(
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
LSB (Least Significant Bit) technique.
"""
hider = tools.Hider(image, message, encoding, auto_convert_rgb)
width = hider.encoded_image.width
while shift != 0:
next(generator)
shift -= 1
while hider.encode_another_pixel():
generated_number = next(generator)
col = generated_number % width
row = int(generated_number / width)
hider.encode_pixel((col, row))
return hider.encoded_image
def reveal(
encoded_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)."""
revealer = tools.Revealer(encoded_image, encoding)
width = revealer.encoded_image.width
while shift != 0:
next(generator)
shift -= 1
while True:
generated_number = next(generator)
col = generated_number % width
row = int(generated_number / width)
if revealer.decode_pixel((col, row)):
return revealer.secret_message

View file

@ -30,7 +30,7 @@ import itertools
import cv2 import cv2
import numpy as np import numpy as np
from stegano.lsbset import generators from stegano.lsb import generators
class TestGenerators(unittest.TestCase): class TestGenerators(unittest.TestCase):
@ -151,7 +151,7 @@ class TestGenerators(unittest.TestCase):
"""Test the LFSR generator""" """Test the LFSR generator"""
with open("./tests/expected-results/LFSR", "r") as f: with open("./tests/expected-results/LFSR", "r") as f:
self.assertEqual( self.assertEqual(
tuple(itertools.islice(generators.LFSR(2 ** 8), 256)), tuple(itertools.islice(generators.LFSR(2**8), 256)),
tuple(int(line) for line in f), tuple(int(line) for line in f),
) )