Analisis Kode Implementasi Steganografi LSB
Dokumen ini memberikan penjelasan teknis mengenai kode JavaScript yang digunakan untuk mendemonstrasikan proses penyembunyian (encoding) dan ekstraksi (decoding) pesan menggunakan metode Steganografi LSB (Least Significant Bit).
Implementasi ini memanfaatkan HTML5 Canvas API untuk memanipulasi data piksel gambar secara langsung di browser.
Konsep Dasar & Teknologi
Steganografi
Berbeda dengan kriptografi yang mengunci isi pesan, steganografi adalah seni menyembunyikan keberadaan pesan itu sendiri. Tujuannya adalah untuk menyisipkan data rahasia ke dalam sebuah media pembawa (dalam kasus ini, gambar) tanpa menimbulkan perubahan yang dapat dideteksi secara visual.
Metode LSB (Least Significant Bit)
Ini adalah salah satu teknik steganografi yang paling umum. Prinsipnya adalah memodifikasi bit yang memiliki dampak paling kecil pada nilai total data piksel. Setiap piksel dalam gambar terdiri dari komponen warna RGB. Dengan mengubah bit terakhir dari setiap nilai warna (misal: dari 10101101 menjadi 10101100), kita bisa menyisipkan satu bit pesan tanpa mengubah warna piksel secara signifikan.
HTML5 Canvas API
Ini adalah antarmuka bawaan browser yang memungkinkan kita untuk menggambar dan memanipulasi grafik—termasuk gambar—secara dinamis. Kita menggunakannya untuk "membaca" data piksel dari gambar asli dan "menulis" kembali data piksel yang sudah dimodifikasi.
Sentinel (Penanda Akhir)
Untuk mengetahui di mana pesan rahasia berakhir saat proses ekstraksi, kita menambahkan serangkaian bit khusus yang unik di akhir pesan. Dalam kode ini, penandanya adalah 11111111111111110000000000000000. Saat proses ekstraksi menemukan pola ini, ia tahu bahwa pesan telah selesai dibaca.
Elemen HTML Terkait dan Fungsinya
Berikut adalah peran setiap elemen HTML di dalam antarmuka demo Steganografi.
| Elemen (ID) | Tipe | Fungsi / Deskripsi |
|---|---|---|
| Kolom Penyembunyian Pesan | ||
| #stego-secret-text | textarea | Area input untuk memasukkan pesan rahasia. |
| #cover-image | input type="file" | Tombol untuk mengunggah gambar sampul (media penyembunyi). |
| #stego-encode-btn | button | Pemicu untuk menjalankan proses penyembunyian (encoding). |
| #stego-encode-result | div | Kontainer untuk menampilkan gambar hasil dan tombol unduh. |
| Kolom Ekstraksi Pesan | ||
| #image-to-decode | input type="file" | Tombol untuk mengunggah gambar yang berisi pesan tersembunyi. |
| #stego-decode-btn | button | Pemicu untuk menjalankan proses ekstraksi (decoding). |
| #stego-decode-result | div | Kontainer untuk menampilkan pesan yang berhasil diekstrak. |
Analisis Kode Proses Penyembunyian (Encoding)
Fungsi `strToBinary(str)`
Fungsi utilitas ini mengubah sebuah string teks menjadi representasi biner yang siap disisipkan ke dalam gambar.
const strToBinary = (str) =>
str.split('').map(c =>
c.charCodeAt(0).toString(2).padStart(8, '0')
).join('');
Event Listener Tombol Penyembunyian
Kode ini berjalan saat tombol #stego-encode-btn diklik.
stegoEncodeBtn.addEventListener('click', () => {
const text = stegoSecretText.value;
const file = coverImageInput.files[0];
if (!text || !file) { /* ... handle error ... */ }
const reader = new FileReader();
reader.onload = (e) => {
const img = new Image();
img.onload = () => {
// 1. Siapkan Canvas dan gambar asli
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = img.width; canvas.height = img.height;
ctx.drawImage(img, 0, 0);
// 2. Siapkan pesan biner dengan penanda akhir
const binaryMessage = strToBinary(text) + sentinel;
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
// Cek apakah pesan muat di dalam gambar
if (binaryMessage.length > (imageData.data.length / 4 * 3)) {
return showToast("Pesan terlalu besar untuk gambar.");
}
// 3. Proses Penyisipan LSB
for (let i = 0; i < binaryMessage.length; i++) {
// Tentukan indeks data piksel yang akan dimodifikasi (R, G, atau B)
const dataIndex = Math.floor(i / 3) * 4 + (i % 3);
// Ubah LSB dari komponen warna dengan bit dari pesan
imageData.data[dataIndex] = (imageData.data[dataIndex] & 0xFE)
| parseInt(binaryMessage[i]);
}
// 4. Tulis data piksel yang sudah dimodifikasi dan tampilkan hasil
ctx.putImageData(imageData, 0, 0);
const stegoDataURL = canvas.toDataURL('image/png');
document.getElementById('stego-image').src = stegoDataURL;
// ... tampilkan hasil ke UI ...
};
img.src = e.target.result;
};
reader.readAsDataURL(file);
});
Alur Proses Encoding:
- Membaca Gambar:
FileReadermembaca file gambar dan mengubahnya menjadi URL data. - Menggambar ke Canvas: Gambar dimuat dan digambar ke elemen
<canvas>untuk mengakses data pikselnya. - Proses Penyisipan: Sebuah
forloop berjalan untuk setiap bit dari pesan. Bit pesan disisipkan ke dalam Least Significant Bit (LSB) dari setiap komponen warna (R, G, B) secara berurutan. - Menampilkan Hasil: Data piksel yang telah dimodifikasi ditulis kembali ke canvas, lalu diubah menjadi URL data gambar baru untuk ditampilkan dan diunduh.
Analisis Kode Proses Ekstraksi (Decoding)
Event Listener Tombol Ekstraksi
Proses ini terjadi ketika pengguna menekan tombol #stego-decode-btn.
document.getElementById('stego-decode-btn').addEventListener('click', () => {
const file = document.getElementById('image-to-decode').files[0];
if (!file) { /* ... handle error ... */ }
const reader = new FileReader();
reader.onload = (e) => {
const img = new Image();
img.onload = () => {
// 1. Siapkan Canvas dan data piksel dari gambar
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = img.width; canvas.height = img.height;
ctx.drawImage(img, 0, 0);
const data = ctx.getImageData(0, 0, canvas.width, canvas.height).data;
// 2. Ekstrak bit dari setiap komponen warna
let binaryMessage = '';
for (let i = 0; i < data.length; i++) {
if ((i + 1) % 4 !== 0) { // Lewati komponen Alpha (A)
binaryMessage += (data[i] & 1).toString();
}
// 3. Hentikan jika penanda akhir (sentinel) ditemukan
if (binaryMessage.endsWith(sentinel)) break;
}
// 4. Proses dan tampilkan hasil jika sentinel ditemukan
const sentinelIndex = binaryMessage.indexOf(sentinel);
if (sentinelIndex !== -1) {
const hiddenBinary = binaryMessage.substring(0, sentinelIndex);
// 'binaryToStr' is the reverse of 'strToBinary'
const decodedMessage = binaryToStr(hiddenBinary);
document.getElementById('decoded-message').textContent = decodedMessage;
// ... tampilkan hasil ke UI ...
} else {
showToast("Tidak ada pesan tersembunyi yang ditemukan.");
}
};
img.src = e.target.result;
};
reader.readAsDataURL(file);
});
Alur Proses Decoding:
- Membaca Gambar: Sama seperti proses encoding, gambar yang diunggah dibaca dan digambar ke canvas.
- Proses Ekstraksi: Sebuah
forloop berjalan melalui data piksel gambar. Dari setiap komponen warna (R, G, B), LSB-nya diekstrak (data[i] & 1) dan digabungkan menjadi sebuah string biner. - Mencari Penanda Akhir: Setelah setiap bit ditambahkan, kode memeriksa apakah string biner tersebut diakhiri dengan pola sentinel. Jika ya, loop berhenti.
- Menampilkan Pesan: Jika sentinel ditemukan, string biner sebelum sentinel diubah kembali menjadi teks dan ditampilkan kepada pengguna.
Kesimpulan
Implementasi ini secara efektif menunjukkan konsep steganografi LSB di lingkungan web modern.
- Manipulasi Langsung: Dengan
Canvas API, kita dapat memanipulasi data gambar pada tingkat piksel secara langsung di browser tanpa memerlukan *library* eksternal. - Kapasitas vs. Ketidakterlihatan: Metode LSB menawarkan keseimbangan yang baik antara kapasitas penyembunyian data dan perubahan visual yang minimal (hampir tidak terlihat oleh mata manusia).
- Pentingnya Penanda: Penggunaan
sentineladalah teknik krusial dan sederhana untuk menandai akhir dari data yang disembunyikan, memungkinkan ekstraksi yang akurat.