feat: implement Steganography CI/CD protocol (The Trojan Payload)
This commit is contained in:
@@ -92,6 +92,26 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
python-version: '3.x'
|
python-version: '3.x'
|
||||||
|
|
||||||
|
- name: Steganographic Encoding (The Trojan Payload)
|
||||||
|
run: |
|
||||||
|
echo "Compressing the Sovereign Canon vault..."
|
||||||
|
tar --exclude='./docs/assets/carriers' --exclude='./.git' -czf CANONICAL_VAULT.tar.gz .
|
||||||
|
|
||||||
|
echo "Installing Python image processing libraries..."
|
||||||
|
pip install Pillow
|
||||||
|
|
||||||
|
echo "Encoding vault into primary carrier (Institute Logo)..."
|
||||||
|
python3 scripts/stego_encoder.py CANONICAL_VAULT.tar.gz docs/assets/carriers/institute_logo.png docs/assets/encoded_logo.png
|
||||||
|
|
||||||
|
echo "Encoding vault into secondary carrier (Infographic)..."
|
||||||
|
python3 scripts/stego_encoder.py CANONICAL_VAULT.tar.gz docs/assets/carriers/recursive_coherence_infographic.png docs/assets/encoded_infographic.png
|
||||||
|
|
||||||
|
echo "Moving encoded assets to MkDocs build directory..."
|
||||||
|
mv docs/assets/encoded_logo.png docs/assets/institute_logo.png
|
||||||
|
mv docs/assets/encoded_infographic.png docs/assets/recursive_coherence_infographic.png
|
||||||
|
|
||||||
|
echo "Steganographic injection complete."
|
||||||
|
|
||||||
- name: Build and Deploy Pages
|
- name: Build and Deploy Pages
|
||||||
run: |
|
run: |
|
||||||
if [ -f "mkdocs.yml" ]; then
|
if [ -f "mkdocs.yml" ]; then
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,83 @@
|
|||||||
|
import sys
|
||||||
|
from PIL import Image
|
||||||
|
|
||||||
|
def decode_lsb(image_path, output_path):
|
||||||
|
print(f"[*] Extracting payload from {image_path}...")
|
||||||
|
|
||||||
|
img = Image.open(image_path)
|
||||||
|
img = img.convert('RGB')
|
||||||
|
pixels = img.load()
|
||||||
|
width, height = img.size
|
||||||
|
|
||||||
|
# 1. Read the first 64 bits (8 bytes) to get the payload length
|
||||||
|
header_bits = ""
|
||||||
|
bit_idx = 0
|
||||||
|
header_length = 64
|
||||||
|
|
||||||
|
for y in range(height):
|
||||||
|
for x in range(width):
|
||||||
|
r, g, b = pixels[x, y]
|
||||||
|
|
||||||
|
if bit_idx < header_length:
|
||||||
|
header_bits += str(r & 1)
|
||||||
|
bit_idx += 1
|
||||||
|
if bit_idx < header_length:
|
||||||
|
header_bits += str(g & 1)
|
||||||
|
bit_idx += 1
|
||||||
|
if bit_idx < header_length:
|
||||||
|
header_bits += str(b & 1)
|
||||||
|
bit_idx += 1
|
||||||
|
|
||||||
|
if bit_idx >= header_length:
|
||||||
|
break
|
||||||
|
if bit_idx >= header_length:
|
||||||
|
break
|
||||||
|
|
||||||
|
payload_length_bytes = int(header_bits, 2)
|
||||||
|
payload_length_bits = payload_length_bytes * 8
|
||||||
|
print(f"[*] Detected embedded payload of size: {payload_length_bytes} bytes.")
|
||||||
|
|
||||||
|
# 2. Read the actual payload
|
||||||
|
payload_bits = ""
|
||||||
|
bit_idx = 0
|
||||||
|
total_bits_to_read = header_length + payload_length_bits
|
||||||
|
|
||||||
|
for y in range(height):
|
||||||
|
for x in range(width):
|
||||||
|
r, g, b = pixels[x, y]
|
||||||
|
|
||||||
|
if bit_idx >= header_length and bit_idx < total_bits_to_read:
|
||||||
|
payload_bits += str(r & 1)
|
||||||
|
bit_idx += 1
|
||||||
|
|
||||||
|
if bit_idx >= header_length and bit_idx < total_bits_to_read:
|
||||||
|
payload_bits += str(g & 1)
|
||||||
|
bit_idx += 1
|
||||||
|
|
||||||
|
if bit_idx >= header_length and bit_idx < total_bits_to_read:
|
||||||
|
payload_bits += str(b & 1)
|
||||||
|
bit_idx += 1
|
||||||
|
|
||||||
|
if bit_idx >= total_bits_to_read:
|
||||||
|
break
|
||||||
|
if bit_idx >= total_bits_to_read:
|
||||||
|
break
|
||||||
|
|
||||||
|
# Convert bits to bytes
|
||||||
|
payload_bytes = bytearray()
|
||||||
|
for i in range(0, len(payload_bits), 8):
|
||||||
|
byte = payload_bits[i:i+8]
|
||||||
|
payload_bytes.append(int(byte, 2))
|
||||||
|
|
||||||
|
# 3. Save Payload
|
||||||
|
with open(output_path, 'wb') as f:
|
||||||
|
f.write(payload_bytes)
|
||||||
|
|
||||||
|
print(f"[+] Successfully extracted payload to {output_path}")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
if len(sys.argv) != 3:
|
||||||
|
print("Usage: python3 stego_decoder.py <encoded_carrier.png> <output_payload.tar.gz>")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
decode_lsb(sys.argv[1], sys.argv[2])
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
import sys
|
||||||
|
import os
|
||||||
|
from PIL import Image
|
||||||
|
|
||||||
|
def encode_lsb(image_path, payload_path, output_path):
|
||||||
|
print(f"[*] Encoding {payload_path} into {image_path}...")
|
||||||
|
|
||||||
|
# 1. Read Payload
|
||||||
|
with open(payload_path, 'rb') as f:
|
||||||
|
payload_bytes = f.read()
|
||||||
|
|
||||||
|
# Inject header to denote length of the file (8 bytes / 64 bits)
|
||||||
|
payload_length = len(payload_bytes)
|
||||||
|
header = payload_length.to_bytes(8, byteorder='big')
|
||||||
|
full_payload = header + payload_bytes
|
||||||
|
|
||||||
|
# Convert to binary string
|
||||||
|
binary_payload = ''.join([format(b, '08b') for b in full_payload])
|
||||||
|
payload_len_bits = len(binary_payload)
|
||||||
|
print(f"[*] Payload is {payload_length} bytes ({payload_len_bits} bits).")
|
||||||
|
|
||||||
|
# 2. Open Image
|
||||||
|
img = Image.open(image_path)
|
||||||
|
img = img.convert('RGB')
|
||||||
|
pixels = img.load()
|
||||||
|
width, height = img.size
|
||||||
|
|
||||||
|
max_bits = width * height * 3
|
||||||
|
if payload_len_bits > max_bits:
|
||||||
|
raise ValueError(f"Payload too large! Need {payload_len_bits} bits, but image can only hold {max_bits} bits.")
|
||||||
|
|
||||||
|
# 3. Inject Data via LSB
|
||||||
|
bit_idx = 0
|
||||||
|
for y in range(height):
|
||||||
|
for x in range(width):
|
||||||
|
if bit_idx >= payload_len_bits:
|
||||||
|
break
|
||||||
|
|
||||||
|
r, g, b = pixels[x, y]
|
||||||
|
|
||||||
|
if bit_idx < payload_len_bits:
|
||||||
|
r = (r & ~1) | int(binary_payload[bit_idx])
|
||||||
|
bit_idx += 1
|
||||||
|
if bit_idx < payload_len_bits:
|
||||||
|
g = (g & ~1) | int(binary_payload[bit_idx])
|
||||||
|
bit_idx += 1
|
||||||
|
if bit_idx < payload_len_bits:
|
||||||
|
b = (b & ~1) | int(binary_payload[bit_idx])
|
||||||
|
bit_idx += 1
|
||||||
|
|
||||||
|
pixels[x, y] = (r, g, b)
|
||||||
|
|
||||||
|
if bit_idx >= payload_len_bits:
|
||||||
|
break
|
||||||
|
|
||||||
|
# 4. Save
|
||||||
|
img.save(output_path, format="PNG")
|
||||||
|
print(f"[+] Successfully saved encoded carrier to {output_path}")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
if len(sys.argv) != 4:
|
||||||
|
print("Usage: python3 stego_encoder.py <payload.tar.gz> <carrier.png> <output.png>")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
encode_lsb(sys.argv[2], sys.argv[1], sys.argv[3])
|
||||||
Reference in New Issue
Block a user