Ejemplo n.º 1
0
def reveal(input_image: Union[str, IO[bytes]],
           encoding: str = "UTF-8",
           shift: int = 0):
    """Find a message in an image (with the LSB technique).
    """
    img = tools.open_image(input_image)
    width, height = img.size
    buff, count = 0, 0
    bitab = []
    limit = None
    for row in range(height):
        for col in range(width):
            if shift != 0:
                shift -= 1
                continue
            # pixel = [r, g, b] or [r,g,b,a]
            pixel = img.getpixel((col, row))
            if img.mode == "RGBA":
                pixel = pixel[:3]  # ignore the alpha
            for color in pixel:
                buff += (color & 1) << (tools.ENCODINGS[encoding] - 1 - count)
                count += 1
                if count == tools.ENCODINGS[encoding]:
                    bitab.append(chr(buff))
                    buff, count = 0, 0
                    if bitab[-1] == ":" and limit is None:
                        try:
                            limit = int("".join(bitab[:-1]))
                        except Exception:
                            pass

            if len(bitab) - len(str(limit)) - 1 == limit:
                img.close()
                return "".join(bitab)[len(str(limit)) + 1:]
Ejemplo n.º 2
0
def hide(
    input_image_file, img_enc, secret_message=None, secret_file=None, img_format=None,
):
    """Hide a message (string) in an image.
    """
    from zlib import compress
    from base64 import b64encode

    if secret_file is not None:
        with open(secret_file, "r") as f:
            secret_message = f.read()

    try:
        text = compress(b64encode(bytes(secret_message, "utf-8")))
    except:
        text = compress(b64encode(secret_message))

    img = tools.open_image(input_image_file)

    if img_format is None:
        img_format = img.format

    if "exif" in img.info:
        exif_dict = piexif.load(img.info["exif"])
    else:
        exif_dict = {}
        exif_dict["0th"] = {}
    exif_dict["0th"][piexif.ImageIFD.ImageDescription] = text
    exif_bytes = piexif.dump(exif_dict)
    img.save(img_enc, format=img_format, exif=exif_bytes)
    img.close()
    return img
Ejemplo n.º 3
0
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).
    """
    img = tools.open_image(input_image)
    img_list = list(img.getdata())
    width, height = img.size
    buff, count = 0, 0
    bitab = []
    limit = None

    while shift != 0:
        next(generator)
        shift -= 1

    while True:
        generated_number = next(generator)
        # color = [r, g, b]
        for color in img_list[generated_number][:3]:  # ignore the alpha
            buff += (color & 1) << (tools.ENCODINGS[encoding] - 1 - count)
            count += 1
            if count == tools.ENCODINGS[encoding]:
                bitab.append(chr(buff))
                buff, count = 0, 0
                if bitab[-1] == ":" and limit == None:
                    if "".join(bitab[:-1]).isdigit():
                        limit = int("".join(bitab[:-1]))
                    else:
                        raise IndexError("Impossible to detect message.")
        if len(bitab) - len(str(limit)) - 1 == limit:
            return "".join(bitab)[len(str(limit)) + 1:]
Ejemplo n.º 4
0
def hide(input_image: Union[str, IO[bytes]], message: str):
    """
    Hide a message (string) in an image.

    Use the red portion of a pixel (r, g, b) tuple to
    hide the message string characters as ASCII values.
    The red value of the first pixel is used for message_length of the string.
    """
    message_length = len(message)
    assert message_length != 0, "message message_length is zero"
    assert message_length < 255, "message is too long"
    img = tools.open_image(input_image)
    # Use a copy of image to hide the text in
    encoded = img.copy()
    width, height = img.size
    index = 0
    for row in range(height):
        for col in range(width):
            (r, g, b) = img.getpixel((col, row))
            # first value is message_length of message
            if row == 0 and col == 0 and index < message_length:
                asc = message_length
            elif index <= message_length:
                c = message[index - 1]
                asc = ord(c)
            else:
                asc = r
            encoded.putpixel((col, row), (asc, g, b))
            index += 1
    img.close()
    return encoded
Ejemplo n.º 5
0
def reveal(input_image_file):
    """Find a message in an image.
    """
    from base64 import b64decode
    from zlib import decompress

    img = tools.open_image(input_image_file)

    try:
        if img.format in ["JPEG", "TIFF"]:
            if "exif" in img.info:
                exif_dict = piexif.load(img.info.get("exif", b""))
                description_key = piexif.ImageIFD.ImageDescription
                encoded_message = exif_dict["0th"][description_key]
            else:
                encoded_message = b""
        else:
            raise ValueError("Given file is neither JPEG nor TIFF.")
    finally:
        img.close()

    return b64decode(decompress(encoded_message))
Ejemplo n.º 6
0
def reveal(input_image: Union[str, IO[bytes]]):
    """
    Find a message in an image.

    Check the red portion of an pixel (r, g, b) tuple for
    hidden message characters (ASCII values).
    The red value of the first pixel is used for message_length of string.
    """
    img = tools.open_image(input_image)
    width, height = img.size
    message = ""
    index = 0
    for row in range(height):
        for col in range(width):
            r, g, b = img.getpixel((col, row))
            # First pixel r value is length of message
            if row == 0 and col == 0:
                message_length = r
            elif index <= message_length:
                message += chr(r)
            index += 1
    img.close()
    return message
Ejemplo n.º 7
0
def hide(
    input_image: Union[str, IO[bytes]],
    message: str,
    encoding: str = "UTF-8",
    shift: int = 0,
    auto_convert_rgb: bool = False,
):
    """Hide a message (string) in an image with the
    LSB (Least Significant Bit) technique.
    """
    message_length = len(message)
    assert message_length != 0, "message length is zero"

    img = tools.open_image(input_image)

    if img.mode not in ["RGB", "RGBA"]:
        if not auto_convert_rgb:
            print("The mode of the image is not RGB. Mode is {}".format(
                img.mode))
            answer = input("Convert the image to RGB ? [Y / n]\n") or "Y"
            if answer.lower() == "n":
                raise Exception("Not a RGB image.")
        img = img.convert("RGB")

    encoded = img.copy()
    width, height = img.size
    index = 0

    message = str(message_length) + ":" + str(message)
    message_bits = "".join(tools.a2bits_list(message, encoding))
    message_bits += "0" * ((3 - (len(message_bits) % 3)) % 3)

    npixels = width * height
    len_message_bits = len(message_bits)
    if len_message_bits > npixels * 3:
        raise Exception("The message you want to hide is too long: {}".format(
            message_length))
    for row in range(height):
        for col in range(width):
            if shift != 0:
                shift -= 1
                continue
            if index + 3 <= len_message_bits:

                # Get the colour component.
                pixel = img.getpixel((col, row))
                r = pixel[0]
                g = pixel[1]
                b = pixel[2]

                # Change the Least Significant Bit of each colour component.
                r = tools.setlsb(r, message_bits[index])
                g = tools.setlsb(g, message_bits[index + 1])
                b = tools.setlsb(b, message_bits[index + 2])

                # Save the new pixel
                if img.mode == "RGBA":
                    encoded.putpixel((col, row), (r, g, b, pixel[3]))
                else:
                    encoded.putpixel((col, row), (r, g, b))

                index += 3
            else:
                img.close()
                return encoded
Ejemplo n.º 8
0
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
    LSB (Least Significant Bit) technique.
    """
    message_length = len(message)
    assert message_length != 0, "message length is zero"

    img = tools.open_image(input_image)

    if img.mode not in ["RGB", "RGBA"]:
        if not auto_convert_rgb:
            print("The mode of the image is not RGB. Mode is {}".format(
                img.mode))
            answer = input("Convert the image to RGB ? [Y / n]\n") or "Y"
            if answer.lower() == "n":
                raise Exception("Not a RGB image.")
        img = img.convert("RGB")

    img_list = list(img.getdata())
    width, height = img.size
    index = 0

    message = str(message_length) + ":" + str(message)
    message_bits = "".join(tools.a2bits_list(message, encoding))
    message_bits += "0" * ((3 - (len(message_bits) % 3)) % 3)

    npixels = width * height
    len_message_bits = len(message_bits)
    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)
        r, g, b, *a = img_list[generated_number]

        # Change the Least Significant Bit of each colour component.
        r = tools.setlsb(r, message_bits[index])
        g = tools.setlsb(g, message_bits[index + 1])
        b = tools.setlsb(b, message_bits[index + 2])

        # Save the new pixel
        if img.mode == "RGBA":
            img_list[generated_number] = (r, g, b, *a)
        else:
            img_list[generated_number] = (r, g, b)

        index += 3

    # create empty new image of appropriate format
    encoded = Image.new(img.mode, (img.size))

    # insert saved data into the image
    encoded.putdata(img_list)

    return encoded