110 lines
4.3 KiB
Rust
110 lines
4.3 KiB
Rust
#![deny(warnings)]
|
|
#![allow(dead_code)]
|
|
// [TSM.ID].[11031972] -- All Rights Reserved. Proprietary & Confidential.
|
|
use anyhow::{anyhow, Result};
|
|
use tracing::{info, debug};
|
|
|
|
/// THE PHANTOM MATRIX (Phase 37)
|
|
/// Algoritma Sub-Pixel Steganography (Least Significant Bit Evasion)
|
|
pub struct PhantomStego;
|
|
|
|
impl PhantomStego {
|
|
/// ENCODER: Menerima data rahasia (video/audio payload) dan menyuntikkannya ke dalam
|
|
/// LSB (bit terkecil) dari sebuah gambar vektor palsu (Array of Pixels/RGB).
|
|
/// Mengembalikan gambar baru yang telah disisipi data tanpa mengubah persepsi warna manusia.
|
|
pub fn encode_payload_to_image(payload: &[u8], mut dummy_image_pixels: Vec<u8>) -> Result<Vec<u8>> {
|
|
info!("PHANTOM MATRIX: Menginjeksi {} bytes data ke dalam {} piksel gambar...", payload.len(), dummy_image_pixels.len() / 3);
|
|
|
|
let _bit_index = 0;
|
|
let total_bits = payload.len() * 8;
|
|
|
|
// Memastikan gambar cukup besar untuk menampung data
|
|
if dummy_image_pixels.len() < total_bits + 32 {
|
|
return Err(anyhow!("Ukuran gambar terlalu kecil untuk menampung payload rahasia!"));
|
|
}
|
|
|
|
// Simpan panjang payload di 32 piksel pertama
|
|
let payload_len = payload.len() as u32;
|
|
for i in 0..32 {
|
|
let bit = (payload_len >> (31 - i)) & 1;
|
|
dummy_image_pixels[i] = (dummy_image_pixels[i] & 0xFE) | (bit as u8);
|
|
}
|
|
|
|
// Suntikkan payload bit demi bit ke sisa piksel
|
|
for i in 0..total_bits {
|
|
let byte_idx = i / 8;
|
|
let bit_idx = 7 - (i % 8);
|
|
let bit = (payload[byte_idx] >> bit_idx) & 1;
|
|
|
|
let pixel_idx = i + 32;
|
|
dummy_image_pixels[pixel_idx] = (dummy_image_pixels[pixel_idx] & 0xFE) | bit;
|
|
}
|
|
|
|
debug!("PHANTOM MATRIX: Injeksi selesai. Gambar siap menyusup ke dalam DPI Firewall.");
|
|
Ok(dummy_image_pixels)
|
|
}
|
|
|
|
/// DECODER: Mengekstrak kembali data rahasia dari gambar palsu.
|
|
pub fn decode_payload_from_image(stego_image_pixels: &[u8]) -> Result<Vec<u8>> {
|
|
if stego_image_pixels.len() < 32 {
|
|
return Err(anyhow!("Gambar tidak memiliki metadata steganografi."));
|
|
}
|
|
|
|
// Ekstrak 32 bit pertama untuk mengetahui panjang data rahasia
|
|
let mut payload_len = 0u32;
|
|
for i in 0..32 {
|
|
let bit = (stego_image_pixels[i] & 1) as u32;
|
|
payload_len |= bit << (31 - i);
|
|
}
|
|
|
|
let total_bits = (payload_len as usize) * 8;
|
|
|
|
if stego_image_pixels.len() < total_bits + 32 {
|
|
return Err(anyhow!("Data steganografi korup atau terpotong."));
|
|
}
|
|
|
|
info!("PHANTOM MATRIX: Mengekstrak {} bytes data rahasia dari gambar...", payload_len);
|
|
let mut payload = vec![0u8; payload_len as usize];
|
|
|
|
for i in 0..total_bits {
|
|
let pixel_idx = i + 32;
|
|
let bit = stego_image_pixels[pixel_idx] & 1;
|
|
|
|
let byte_idx = i / 8;
|
|
let bit_idx = 7 - (i % 8);
|
|
payload[byte_idx] |= bit << bit_idx;
|
|
}
|
|
|
|
Ok(payload)
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_phantom_visual_evasion() {
|
|
let rahasia_negara = b"XCU-OPERATION-PHANTOM-PROTOCOL-OVERRIDE";
|
|
|
|
// Simulasi RGB Pixel sebuah gambar putih beresolusi sangat kecil (Cukup menampung string)
|
|
// 40 bytes string = 320 bits + 32 bit header = 352 pixels dibutuhkan minimum.
|
|
let mut dummy_image = vec![255u8; 1000]; // 1000 pixels
|
|
|
|
// ENKODE: Menyamarkan rahasia negara ke dalam gambar
|
|
let stego_image = PhantomStego::encode_payload_to_image(rahasia_negara, dummy_image.clone()).unwrap();
|
|
|
|
// Bukti Visual (Matematis): Piksel nyaris tidak berubah (255 menjadi 254)
|
|
// Mata telanjang manusia tidak akan melihat perbedaan RGB 255 dan RGB 254.
|
|
for i in 0..352 {
|
|
assert!(stego_image[i] == 255 || stego_image[i] == 254);
|
|
}
|
|
|
|
// DEKODE: Menarik rahasia negara dari gambar palsu
|
|
let extracted_rahasia = PhantomStego::decode_payload_from_image(&stego_image).unwrap();
|
|
|
|
assert_eq!(rahasia_negara.to_vec(), extracted_rahasia);
|
|
println!("VISUAL EVASION TEST BERHASIL: Rahasia disembunyikan dalam gambar dan ditarik 100% utuh tanpa kerusakan!");
|
|
}
|
|
}
|