Bases: BaseCodec
SteganographyTxt
This module implements simple LSB steganography in images.
- To encode: The input message is converted into binary, and the message is embedded
into the least significant bits (LSB) of the input image rgb. Once the message is
encoded, a trailing delimiter is written. The resulting image is saved as a PNG
file.
- To decode: The least significant bits of the input image are read off until the
decode bit number more than datalenth. After which the secret message would be
recovered.
Originally implemented in
raffg/steganography
Source code in stegobox/codec/steganography_txt.py
| class SteganographyTxt(BaseCodec):
"""SteganographyTxt
This module implements simple LSB steganography in images.
* To encode: The input message is converted into binary, and the message is embedded
into the least significant bits (LSB) of the input image rgb. Once the message is
encoded, a trailing delimiter is written. The resulting image is saved as a PNG
file.
* To decode: The least significant bits of the input image are read off until the
decode bit number more than datalenth. After which the secret message would be
recovered.
Originally implemented in
[raffg/steganography](https://github.com/raffg/steganography)
"""
def __init__(self) -> None:
super().__init__()
def encode(self, carrier: Image.Image, payload: str) -> Image.Image:
self._check_empty_payload(payload)
# Convert image to ndarrray
img = np.array(carrier)
# Convert payload to binary (removes leading '0b')
byte_s = payload.encode("utf-8")
hex_bin = byte_s.hex()
oct_bin = oct(int(hex_bin, 16))
binary_bin = bin(int(oct_bin, 8))[2:].zfill(len(hex_bin) * 4)
# Convert the length of data to binary (removes leading '0b')
lenth_bin = bin(len(binary_bin))[2:].zfill(12)
binary_bin = lenth_bin + binary_bin
data_lenth = len(binary_bin)
h, w, s = img.shape
# Embed the message in the image
num = 0
for i in range(h):
for j in range(w):
for k in range(s):
if img[i][j][k] % 2 == 1:
if binary_bin[num] == "0":
img[i][j][k] = img[i][j][k] - 1
else:
if binary_bin[num] == "1":
img[i][j][k] = img[i][j][k] + 1
num = num + 1
if num >= data_lenth:
break
if num >= data_lenth:
break
if num >= data_lenth:
break
new_img = Image.fromarray(img)
return new_img
def decode(self, carrier: Image.Image) -> str:
extract = ""
img = np.array(carrier)
h, w, s = img.shape
img = np.array(carrier)
num = 0
# initial the data_lenth
data_lenth = 13
for i in range(h):
for j in range(w):
for k in range(s):
if img[i][j][k] % 2 == 1:
extract += "1"
else:
extract += "0"
num = num + 1
if num == 12:
data_lenth = int(extract[:12], 2) + 12
if num >= data_lenth:
break
if num >= data_lenth:
break
if num >= data_lenth:
break
# Convert binary to payload
return bytes.fromhex(hex(int(extract[12:], 2))[2:]).decode("utf-8")
def _check_empty_payload(self, payload: str) -> None:
if not payload:
raise Exception("Payload must not be empty.")
|