From b1d49d52356b1cb4f8bad99f6f565bbf75d4ee66 Mon Sep 17 00:00:00 2001 From: Dimitri Merejkowsky Date: Thu, 27 Jun 2019 12:00:01 +0200 Subject: [PATCH] stegano soluce --- sources/stegano/requirements.lock | 21 ++++++++ sources/stegano/setup.cfg | 24 +++++++++ sources/stegano/setup.py | 2 + sources/stegano/stegano.py | 82 +++++++++++++++++++++++++++++++ sources/stegano/test_stegano.py | 9 ++++ 5 files changed, 138 insertions(+) create mode 100644 sources/stegano/requirements.lock create mode 100644 sources/stegano/setup.cfg create mode 100644 sources/stegano/setup.py create mode 100644 sources/stegano/stegano.py create mode 100644 sources/stegano/test_stegano.py diff --git a/sources/stegano/requirements.lock b/sources/stegano/requirements.lock new file mode 100644 index 0000000..d274567 --- /dev/null +++ b/sources/stegano/requirements.lock @@ -0,0 +1,21 @@ +# Generated with dmenv 0.15.0, python 3.7.1, on Linux +appdirs==1.4.3 +atomicwrites==1.3.0 +attrs==19.1.0 +black==19.3b0 +Click==7.0 +importlib-metadata==0.18 +more-itertools==7.1.0 +packaging==19.0 +Pillow==6.0.0 +pip==19.1.1 +pluggy==0.12.0 +py==1.8.0 +pyparsing==2.4.0 +pytest==4.6.3 +setuptools==41.0.1 +six==1.12.0 +toml==0.10.0 +wcwidth==0.1.7 +wheel==0.33.4 +zipp==0.5.1 diff --git a/sources/stegano/setup.cfg b/sources/stegano/setup.cfg new file mode 100644 index 0000000..0f130ea --- /dev/null +++ b/sources/stegano/setup.cfg @@ -0,0 +1,24 @@ +[metadata] +name = stegano +version = 0.1.0 +description = simple steagography script +author = e2l + +[options] +py_modules = ["stegano"], + +install_requires = + Pillow + +classifiers = + "Programming Language :: Python :: 3" + + +[options.extras_require] +dev = + black + pytest + +[options.entry_points] +console_scripts = + stegano = stegano:main diff --git a/sources/stegano/setup.py b/sources/stegano/setup.py new file mode 100644 index 0000000..8bf1ba9 --- /dev/null +++ b/sources/stegano/setup.py @@ -0,0 +1,2 @@ +from setuptools import setup +setup() diff --git a/sources/stegano/stegano.py b/sources/stegano/stegano.py new file mode 100644 index 0000000..e3539a1 --- /dev/null +++ b/sources/stegano/stegano.py @@ -0,0 +1,82 @@ +import PIL.Image +import itertools + +import sys + + +def get_bitstream(message): + for c in message: + bin_string = "{:08b}".format(c) + for bit in bin_string: + yield int(bit) + + +def parse_bitstream(stream): + for bits in by_chunk(stream, 8, fillvalue=0): + binstr = "".join([str(b) for b in bits]) + c = int(binstr, 2) + if chr(c) == "\n": + break + yield c + + +def by_chunk(iterable, size, fillvalue=0): + "Collect data into fixed-length chunks or blocks" + args = [iter(iterable)] * size + return itertools.zip_longest(*args, fillvalue=fillvalue) + + +def set_bit(old_byte, new_bit): + b = list(bin(old_byte)) + b[-1] = str(new_bit) + return int("".join(b), 2) + + +def main_encrypt(): + base_name = sys.argv[2] + message = (sys.argv[3] + "\n").encode() + carrier_name = base_name.replace(".png", ".carrier.png") + base_image = PIL.Image.open(base_name) + width, height = base_image.size + new_image = PIL.Image.new("RGB", (width, height), "white") + bitstream = get_bitstream(message) + for row in range(height): + for col in range(width): + r, g, b = base_image.getpixel((col, row)) + value = None + try: + value = next(bitstream) + except StopIteration: + pass + if value is not None: + r = set_bit(r, value) + new_image.putpixel((col, row), (r, g, b)) + + new_image.save(carrier_name, "png") + print("carrier written to", carrier_name) + + +def yield_bits(carrier_image): + width, height = carrier_image.size + for row in range(height): + for col in range(width): + r, g, b = carrier_image.getpixel((col, row)) + last_bit = int(bin(r)[-1]) + yield last_bit + + +def main_decrypt(): + carrier_name = sys.argv[2] + carrier_image = PIL.Image.open(carrier_name) + encoded = yield_bits(carrier_image) + decoded = bytes(parse_bitstream(encoded)) + print(decoded.decode()) + + +def main(): + if sys.argv[1] == "encrypt": + main_encrypt() + elif sys.argv[1] == "decrypt": + main_decrypt() + else: + sys.exit("choose from encrypt, decrypt") diff --git a/sources/stegano/test_stegano.py b/sources/stegano/test_stegano.py new file mode 100644 index 0000000..a23bf44 --- /dev/null +++ b/sources/stegano/test_stegano.py @@ -0,0 +1,9 @@ +import stegano + + +def test_message_conversion(): + message = b"I love you\ngarbage" + encoded = list(stegano.get_bitstream(message)) + + decoded = bytes(stegano.parse_bitstream(encoded)) + assert decoded == b"I love you"