Bases: BaseCodec
Hide str in bitmap type images using LSB steganography.
- To encode: First we get the representation of the message as a list of bits.
Next we get a cover vector of 128 pixels in which we are going to hide the
message. Then, we modify the cover vector obtaining the stego vector modifying
the LSB of each byte to embed the message bit. Finally, we save the image with
the modified data.
- To decode: The least significant bits of the encoded image are read to recover
the secret message.
Originally implemented at
daniellerch.me
Source code in stegobox/codec/bmp_lsb.py
| class BMPLsb(BaseCodec):
"""Hide str in bitmap type images using LSB steganography.
* To encode: First we get the representation of the message as a list of bits.
Next we get a cover vector of 128 pixels in which we are going to hide the
message. Then, we modify the cover vector obtaining the stego vector modifying
the LSB of each byte to embed the message bit. Finally, we save the image with
the modified data.
* To decode: The least significant bits of the encoded image are read to recover
the secret message.
Originally implemented at
[daniellerch.me](https://daniellerch.me/stego/lab/intro/lsb-en/#lsb-steganography-in-bitmap-images)
"""
def __init__(self) -> None:
super().__init__()
def encode(self, carrier: Image.Image, payload: str) -> Image.Image:
"""Encode the string payload into the carrier image using LSB steganography.
Args:
carrier: Carrier image in format PNG. Read with `stegobox.io.image.read()`.
payload: Payload (secret message) to be encoded.
Returns:
Encoded image in format PNG with the payload embeded.
"""
self._check_empty_payload(payload)
c = numpy.array(carrier)
c.flags.writeable = True
message_bits = []
for m in payload:
message_bits += [(ord(m) >> i) & 1 for i in range(8)]
cover = c[:128, 0, 0]
stego = cover.copy()
for i in range(len(message_bits)):
if cover[i] % 2 != message_bits[i]:
if cover[i] == 255:
s = -1
elif cover[i] == 0:
s = +1
else:
s = random.choice([-1, +1])
stego[i] = cover[i] + s
c[:128, 0, 0] = stego
secret_image = Image.fromarray(numpy.uint8(c))
return secret_image
def decode(self, carrier: Image.Image, payload_l: int = 10) -> str:
"""Decode the secret message from the carrier image.
Args:
carrier: The container image in format PNG with the secret message.
payload_l: The length of the secret message to extracted, defaults to 10.
Returns:
str: The reveal_payload extracted from the container image.
"""
carrier_np = numpy.array(carrier)
stego = carrier_np[:128, 0, 0]
message_bits = [s % 2 for s in stego]
message_ex = []
value = 0
for i in range(len(message_bits)):
if i % 8 == 0 and i != 0:
message_ex.append(value)
value = 0
value |= message_bits[i] << i % 8
depayload = "".join([chr(m) for m in message_ex])[:payload_l]
return depayload
def _check_empty_payload(self, payload: str) -> None:
if not payload:
raise Exception("Payload must not be empty.")
|
encode(carrier, payload)
Encode the string payload into the carrier image using LSB steganography.
Parameters:
Name |
Type |
Description |
Default |
carrier |
Image
|
Carrier image in format PNG. Read with stegobox.io.image.read() .
|
required
|
payload |
str
|
Payload (secret message) to be encoded.
|
required
|
Returns:
Type |
Description |
Image
|
Encoded image in format PNG with the payload embeded.
|
Source code in stegobox/codec/bmp_lsb.py
| def encode(self, carrier: Image.Image, payload: str) -> Image.Image:
"""Encode the string payload into the carrier image using LSB steganography.
Args:
carrier: Carrier image in format PNG. Read with `stegobox.io.image.read()`.
payload: Payload (secret message) to be encoded.
Returns:
Encoded image in format PNG with the payload embeded.
"""
self._check_empty_payload(payload)
c = numpy.array(carrier)
c.flags.writeable = True
message_bits = []
for m in payload:
message_bits += [(ord(m) >> i) & 1 for i in range(8)]
cover = c[:128, 0, 0]
stego = cover.copy()
for i in range(len(message_bits)):
if cover[i] % 2 != message_bits[i]:
if cover[i] == 255:
s = -1
elif cover[i] == 0:
s = +1
else:
s = random.choice([-1, +1])
stego[i] = cover[i] + s
c[:128, 0, 0] = stego
secret_image = Image.fromarray(numpy.uint8(c))
return secret_image
|
decode(carrier, payload_l=10)
Decode the secret message from the carrier image.
Parameters:
Name |
Type |
Description |
Default |
carrier |
Image
|
The container image in format PNG with the secret message.
|
required
|
payload_l |
int
|
The length of the secret message to extracted, defaults to 10.
|
10
|
Returns:
Name | Type |
Description |
str |
str
|
The reveal_payload extracted from the container image.
|
Source code in stegobox/codec/bmp_lsb.py
| def decode(self, carrier: Image.Image, payload_l: int = 10) -> str:
"""Decode the secret message from the carrier image.
Args:
carrier: The container image in format PNG with the secret message.
payload_l: The length of the secret message to extracted, defaults to 10.
Returns:
str: The reveal_payload extracted from the container image.
"""
carrier_np = numpy.array(carrier)
stego = carrier_np[:128, 0, 0]
message_bits = [s % 2 for s in stego]
message_ex = []
value = 0
for i in range(len(message_bits)):
if i % 8 == 0 and i != 0:
message_ex.append(value)
value = 0
value |= message_bits[i] << i % 8
depayload = "".join([chr(m) for m in message_ex])[:payload_l]
return depayload
|