Download Source : Contoh Aplikasi Steganografi, DCPChiper
Steganografi berasal dari bahasa Yunani, yaitu Steganos yang berarti tersembunyi atau terselubungdan graphein yang berarti menulis. Dari kedua kata tersebut dapat disimpulkan definisi dariSteganografi yaitu suatu ilmu dan seni untuk menyembunyikan pesan atau data rahasia ke dalam pesan atau data yang lain, dengan tujuan pesan atau data rahasia tersebut tidak diketahui keberadaanya oleh pihak yang tidak berhak.Teknik steganografi ini sebenarnya sudah dikenal sejak ribuan tahun lalu, yang biasa digunakan oleh kerajaan-kerajaan kuno dalam setiap aktivitas militernya. Beberapa metode yang digunakan misalnya dengan mentato pesan pada kulit kepala seorang budak dan ketika rambutnya tumbuh dan menutupi pesan rahasia tersebut barulah budak tersebut diutus untuk menyampaikan pesan rahasia ke pada sekutunya. Metode lain yang digunakan adalah dengan menulis pesan rahasia dengan tinta yang tak terlihat yang terbuat dari air sari buah jeruk atau susu. Kemudian untuk membaca pesan tersebut dilakukan dengan memanaskannya di atas nyala api, dan karena terkena panas, area yang dibubuhi tinta tak terlihat perlahan-lahan berubah menjadi gelap sehingga pesan bisa dibaca. Metode ini pertama kali digunakan pada zaman Romawi kuno dan sempat pula digunakan pada masa perang dunia II.
Dan seakarang pada era teknologi yang serba digital, teknik steganografi ini juga digunakan untuk melindungi data yang sifatnya rahasia dan melengkapi teknik keamanan informasi kriptografi (teknik ini mudah-mudahan bisa di jelaskan pada artikel selanjutnya).
Dalam ilmu steganografi dikenal dua istilah yaitu carrier dan content. Di mana carrier adalah media yang digunakan untuk menampung data rahasia. Sedangkan content merupakan pesan atau data yang akan disembunyikan. Pada sistem digital carrier maupun content bisa berupa file gambar, suara, video, teks maupun jenis data yang lain. Yang perlu diketahui di sini adalah bahwa ukuran file carrier harus lebih besar dari file content, sedemikian sehingga output dari proses penyembunyian data tidak berbeda dengan file carrier sumber. Mengingat metode yang digunakan pada proses steganografi sangat banyak, maka di sini hanya akan dijelaskan beberapa teknik steganografi, yaitu:
Penyisipan (Insertion) pada Least Significant Bit(LSB)
Teknik ini dilakukan dengan menyisipkan setiap bit content (data rahasia) ke dalam bit rendah atau bit paling kanan atau disebut juga Least Significant Bit (LSB) dari data carrier (file penampung). Sebagai contoh pada file carrier berupa file gambar/image, seperti diketahui sebuah file bitmap (BMP) 24bit terdiri dari 3 pixel dimana setiap pixel merupakan kumpulan dari 8 bit atau 1 byte (yang bernilai antara 0 sampai 255 atau dalam format biner antara 00000000 sampai 11111111) yang merepresentasikan nilai intensitas cahaya yang membentuk warna dasar yaitu merah, hijau atau biru (Red-Green-Blue atau RGB). Dengan demikian pada setiap 1 pixel bitmap 24bit dapat disisipkan 3 bit content. Pertanyaannya kenapa kita harus menyisipkan pada bagian LSB? Jawabannya karena penyisipan pada bit LSB tidak akan mengubah nilai pixel secara drastis, sehingga secara kasat mata warna pada setiap pixel sebelum dan setelah disisipi tidak akan terlihat berbeda. Keuntungan dari teknik ini adalah penerapan algoritma yang memang sangat mudah dan dalam prosesnya tidak membutuhkan waktu yang lama. Kelemahannya adalah sangat mudah untuk dipecahkan (jika penyisipan dilakukan secara taratur menurut urutan bit), sebagai contoh jika seorang attacker mempunyai stego file(file carrier yang sudah disisipi), maka untuk memcahkannya attacker tersebut mempunyai dua opsi, yaitu:
� Katakanlah attacker tersebut yakin bahwa file telah disisipi pesan, maka untuk memcahkannya cukup dengan mengambil bit LSB pada setiap byte kemudian menganalisa dan menerjemahkannya.
� Ketika attacker tidak yakin file telah disisipi pesan, maka untuk memecahkannya attacker berusaha menemukan sebuah file yang kira-kira sama sebagai pembanding untuk mendapatkan bit LSB dan kemudian menerjemahkannya.
Kedua kasus di atas mengkin bisa di atasi dengan menggunakan sebuah algoritma baku (yang menempatkan bit secara acak) pada proses encoding dan decoding atau dengan mengkombinasikan teknik steganografi dan kriptografi dan saya kira masih banyak solusi lain untuk mengatasi masalah ini.
Seperti diketahui, teknik penyisipan LSB ini dilakukan dengan mengganti bit paling kanan atau bit LSB dengan bit data yang akan disembunyikan. Sebagai contoh, jika kita menggunakan file bitmap 24bit sebagai file carrier dan data rahasia (content) berupa sebuah karakter A yang bernilai biner 01000001 (8 bit), maka untuk menyembunyikan karakter A tersebut kita membutuhkan 3 pixel (3 * 3 byte = 9 byte = 9 LSB, karena A merupakan 8 bit maka 1 LSB terakhir tidak digunakan). Misalnya file bitmap 24bit tersebut mempunya 3 pixel seperti di bawah ini :
10011100 00110110 01100111
00110101 11100101 10011010
11000110 10101101 00010111
Setelah kita melakukan penyisipan bit dari karakter A, maka data pixel di atas akan terlihat seperti di bawah ini :
10011100 00110111 01100100
00110100 11100100 10011010
11000110 10101101 00010111
Dari data pixel tersebut terlihat ada 4 bit rendah yang berubah (dicetak tebal). Sehingga jika data pixel tersebut direpresentasikan ke dalam susunan warna, maka tidak akan terlihat berbeda bagi penglihatan manusia.
Bit-Plane Complexity Segmentation (BPCS)
Teknik yang pertama kali diperkenalkan oleh R. O. Eason dan Eiji Kawaguchi pada tahun 1997 ini merupakan teknik steganografi yang memanfaatkan perhitungan kompeksitas setiap bit plane untuk menyisipkan data. Teknik ini dilakukan dengan membagi media carrier menjadi segmen-segmen di mana setiap segmen berukuran 8 x 8 pixel. Penyisipan data dilakukan pada segmen yang memiliki kompleksitas yang tinggi (noise like regions). Berbeda halnya dengan teknik penyisipan LSB yang hanya menggunakan 1 bit rendah, dengan teknik BPCS data tidak hanya disisipkan pada LSB, tapi juga seluruh bit plane. Untuk mengukur kompleksitas suatu media citra digital kita bisa menggunakan rumus berikut:
? = k/n
Dengan ? adalah nilai kompleksitas, k adalah jumlah perubahan warna dan n adalah probabilitas maksimal perubahan warna.
Penyebaran Spektrum (Spread Spectrum)
Teknik ini biasa digunakan jika media carrier berupa file audio seperti mp3 dan sejenisnya. Teknik ini dilakukan dengan mengkodekan dan mendistribusikan bit-bit pesan ke setiap spektrum frekuensi yang memungkinkan secara acak, sehingga akan sulit bagi seorang attacker untuk memecahkannya, kecuali attracker tersebut dapat merekonstruksi sinyal random yang digunakan untuk menyebarkan data pesan.
Echo Hiding
Sama seperti teknik penyebaran spektrum, teknik ini juga biasa digunakan pada media carrier berupa file audio. Data pesan disembunyikan dengan menyamarkan pesan tersebut ke dalam sinyal yang membentuk echo. Hal ini dilakukan dengan memvariasikan nilai tiga parameter dalam sebuah echo, yaitu besaran amplitudo awal, tingkat penurunan atenuasi (besaran pelemahan energi sinyal) dan offset.
Itulah beberapa contoh teknik yang digunakan dalam ilmu steganografi, sebenarnya masih banyak teknik-teknik lain yang lebih kompleks, karena keterbatasan waktu, ruang dan juga pengetahuan saya jadi untuk saat ini saya rasa penjelasan di atas cukup memberikan gambaran dasar mengenai steganografi. Mudah-mudahan diartikel selanjutnya kita bisa membahas lebih jauh mengenai teknik steganografi, apa itu steganalisis dan stego system dan hal-hal lain yang masih dalam cakupan ilmu steganografi.
Aplikasi Steganografi
Basa basi saya rasa cukup ya.. jadi langsung saja kita masuk ke point utama dari artikel ini yaitu implementasi teknik steganografi dalam bentuk sebuah program. Di sini kita mencoba membuat sebuah program steganografi sederhana dan tentunya juga menggunakan teknik steganografi yang paling sederhana dan mudah yaitu penyisipan LSB. Walaupun terbilang sederhana, tapi keamanaan informasi tetaplah hal utama yang harus diperhatikan. Untuk itu dalam prakteknya saya mengkombinasikan steganografi penyisipan LSB dengan algoritma kriptografi RC4. Perlu diketahui untuk keperluan kriptografi kita menggunakan sebuah komponen built in yaitu DCPChiper dan bisa anda download DI SINI.
Masih sama seperti artikel sebelumnya Delphi 7 menjadi pilihan utama untuk menerapkan steganografi ke dalam sebuah program.
Ok, sekarang siapkan sebuah project yang berisi komponen 2 TImage, 2 TButton untuk Reset, 2 TButton masing-masing bersungsi sebagi trigger Encoding dan Decoding, 2 TMemo sebagai interface masukan data pesan pada proses Encoding dan Decoding. Saya tidak ingin membatasi bagaimana anda mengatur setiap komponen dalam form, jadi itu adalah mutlak berdasarkan kehendak anda dan saya rasa akan membutuhkan banyak ruang untuk menggambarkan komponen dan properti yang digunakan pada contoh aplikasi kali ini. Dan jika tidak mau repot membuat project baru anda juga bisa mempelajari contoh project yang disertakan
Note: Tipe file yang akan kita gunakan sebagai media carrier pada contoh kali ini adalah file bitmap (BMP) 24bit.
Sebelum masuk lebih dalam ke pembahasan program, ada baiknya kita mengenal beberapa fungsi dan properti yang kita gunakan. Beberapa di antaranya:
Str, procedure delphi yang digunakan untuk konversi atau memformat tipe data integer ke tipe data string. Fungsi ini terdiri dari 2 parameter yaitu nilai integer yang akan dikonversi dan variable string untuk menyimpan nilai balik.
Trunc, adalah fungsi delphi untuk konversi tipe data real (pecahan) ke tipe data integer (bulat). Fungsi ini hanya meminta nilai data real sebagai masukan untuk dikonversi dan tentunya kita membutuhkan variable eksternal untuk menerima nilai baliknya.
Exp, fungsi delphi untuk melakukan operasi eksponensial atau pemangkatan. Hanya membutuhkan sebuah parameter masukan nilai angka yang akan dipangkatkan dan hasil operasinya akan disimpan pada eksternal variable.
Ord, fungsi yangdigunakan untuk mendapatkan nilai posisi atau urutan dari sebuah data. Data bisa berupa integer, karakter dan lain-lain.
Chr, fungsi untuk mendapatkan karakter dalam bentuk AnsiChar maupun WideChar dari sebuah nilai posisi berupa integer.
GetPixel, adalah fungsi untuk mendapatkan data pixel pada sebuah area canvas, apakah itu canvas TImage, form dan lain-lain. Fungsi ini memutuhkan 3 nilai paramter yakni handle canvas sumber, indeks kolom pixel dan indeks baris pixel.
GetRValue, GetGValue, GetBValue, masing-masing adalah fungsi untuk mengambil nilai warna merah, hijau dan biru pada sebuah nilai pixel (nilai pixel bisa juga didapatkan dari hasil fungsi GetPixel).
Pixels, merupakan sebuah property dari object TCanvas, yang mempunyai 2 buah direktiv yaitu x dan y yang mewakili titik koordinat baris dan kolom.
Setelah mengetahui sedikit fungsi dasar yang akan kita gunakan barulah kita bisa memahami alur dari setiap fungsi yang kita buat untuk mendukung proses dalam program. Perhatikan potongan script berikut.
function getByte(Number: Byte): String;
var i : integer;
Bit : String[1];
Return : string[8];
begin
i := 0;
Return := �00000000�;
if Number <> 0 then begin
while Number <> 1 do begin
Str(Number mod 2,Bit);
Return[8-i] := Bit[1];
Number := Trunc(Number/2);
Inc(i);
end;Str(Number,Bit);
Return[8-i] := Bit[1];
end;Result := Return;
end;
Fungsi getByte akan digunakan untuk mengkonversi sebuah nilai integer yang masih bisa direpresentasikan ke dalam 8 bit biner. Range integer yang bisa dikonversi yaitu antara 0 sampai dengan 255. Parameter yang bisa diinputkan ke fungsi ini adalah byte dan keluarannya atau nilai baliknya merupakan string. Jika terdapat sebuah nilai data yang lebih dari 255 maka kita membutuhkan sebuah fungsi yang bisa melakukan konversi ke 16 bit binari.
function getWord(Number: Word): String;
var i : integer;
Bit : String[1];
Return : string[16];
begin
i := 0;
Return := �0000000000000000�;
if Number <> 0 then begin
while Number <> 1 do begin
Str(Number mod 2,Bit);
Return[16-i] := Bit[1];
Number := Trunc(Number/2);
Inc(i);
end;Str(Number,Bit);
Return[16-i] := Bit[1];
end;Result := Return;
end;
getWord nantinya akan mengambil peran untuk mengkonversi data yang bernilai 256 dan seterusnya (tipe data word). Karena nilai balik dari fungsi ini adalah 16 bit binari, maka data yang proses oleh fungsi haruslah data yang bisa direpresentasikan dengan 16 bit biner. Sebenarnya range data byte juga bisa dikonversi dengan menggunakan fungsi ini, tapi dalam praktik kita kali ini fungsi getWord hanya digunakan untuk data di atas 255.
Jika kita perhatikan kedua fungsi di atas, sama-sama memiliki tipe keluaran yang sama yakni string bit biner. Dan pada proses tertentu kita harus melakukan konversi sebaliknya, yakni mengubah string bit biner ke dalam nilai numeric atau integer. Untuk itu kita membutuhkan sebuah fungsi yang bisa melakukan konversi tersebut.
function getDecimal(Bit: String): Integer;
var i : Integer;
Return: Integer;
begin
Return := 0;
for i := 1 to Length(Bit) do begin
if Bit[i] = �1� then Return := Return + Trunc(Exp((Length(Bit)-i)*ln(2)));
end;Result := Return;
end;
Fungsi getDecimal mengembalikan nilai integer dari sebuah data input berupa string yang berformat biner yakni 00000000 � 11111111 (8 bit = byte) atau 0000000000000000 � 1111111111111111 (16 bit = word).
Dua fungsi berikut merupakan fungsi kriptografi yakni untuk enkripsi dan dekripsi data pesan. Pada proses penyisipan data akan dienkrip terlebih dahulu dan kemudian ketika proses penguraian data pesan harus didekrip ke bentuk susunan karakter yang bisa dibaca.
function TfrmMain.doEncrypt(Pass, Content: String): String;
var Cipher: TDCP_rc4;
begin
try
Cipher:= TDCP_rc4.Create(Self);
Cipher.InitStr(Pass,TDCP_sha1);
Result := Cipher.EncryptString(Content);Cipher.Burn;
Cipher.Free;
except
Result := �;
end;
end;function TfrmMain.doDecrypt(Pass, Content: String): String;
var Cipher: TDCP_rc4;
begin
try
Cipher:= TDCP_rc4.Create(Self);
Cipher.InitStr(Pass,TDCP_sha1);
Result := Cipher.DecryptString(Content);Cipher.Burn;
Cipher.Free;
except
Result := �;
end;
end;
Seperti yang telah disebutkan sebelumnya, pada module enkripsi dan dekripsi kita membutuhkan fungsi built in dari komponen kriptografi DCPChiper dan RC4 merupakan algoritma yang kita gunakan untuk mengacak data pesan seperti terlihat pada block definisi variable Cipher: TDCP_rc4. Sebenarnya masih banyak algoritma yang disediakan oleh komponen DCPChiper seperti DES, RIJNDAEL, ICE, BLOWFISH serta beberapa algoritma dan fungsi hash lainnya, namun karena alasan kemudahan dan sesuai dengan tujuan program kali ini, maka saya memilih untuk menggunakan algoritma RC4.
Algoritma RC4 termasuk dalam kelompok algoritma konvensional dan merupakan algoritma simetri yakni algoritma yang menggunakan kunci atau password yang sama pada proses enkripsi dan dekripsi. Karena alasan itu juga saya memilih untuk mengimplementasikan algoritma RC4 pada badan program. Pada urutan proses program nantinya user akan diminta untuk memasukkan password yang sama saat akan menyisipkan maupun menguraikan data pesan.
Selanjutnya perhatikan potongan script berikut :
function TfrmMain.CarrierCheck(img: TBitmap): Boolean;
var i: Integer;
Red, Green, Blue: Integer;
strMark, bitLSB: String;
begin
try
bitLSB := �;
for i := 0 to 7 do begin
Red := GetRValue(GetPixel(img.Canvas.Handle,i,0)); //mengambil nilai warna merah pada data pixel pada baris pertama
Green := GetGValue(GetPixel(img.Canvas.Handle,i,0)); //mengambil nilai warna hijau pada data pixel pada baris pertama
Blue := GetBValue(GetPixel(img.Canvas.Handle,i,0)); //mengambil nilai warna biru pada data pixel pada baris pertamabitLSB := bitLSB + getByte(Blue)[8] + getByte(Green)[8] + getByte(Red)[8]; //menyusun bit LSB pada setiap byte warna
end;strMark := Chr(getDecimal(Copy(bitLSB,1,8))) +
Chr(getDecimal(Copy(bitLSB,9,8))) +
Chr(getDecimal(Copy(bitLSB,17,8))); //konversi bit binary ke dalam bentuk karakter yang bisa dibacaResult := strMark = �@d@�; // string @d@ merupakan penanda bahwa file sudah terisi pesan
except
Result := False;
end;
end;
Fungsi CarrierCheck nantinya digunakan untuk mengecek apakah file bitmap sudah disisipi atau mengandung pesan. Sebagai indikator kita membuat sebuah string baku yakni @d@ untuk menandakan apakah file bitmap tersebut sudah disisipi pesan atau belum. Data string @d@ akan disisipkan pada 8 pixel pertama (0 � 7 merupakan 8 indeks pixel pertama) pada wilayah pixel bitmap dan penyisipannya tentu dilakukan bersamaan dengan penyisipan data pesan. Pengecekan dilakukan dengan mengambil nilai masing-masing warna dasar RGB kemudian mengkonversinya ke bentuk biner 8 bit supaya bisa mendapatkan bit LSB pada setiap byte warna. Bit LSB tersebut kemudian ditampung dalam variable bitLSB yang nantinya akan dikonversi ke bentuk plain text (karakter yang bisa dibaca) dengan menggunakan fungsi Chr. Hasil dari fungsi ini adalah boolean yang bernilai antara true ketika nilai variable bitLSB adalah @d@ atau false jika nilai bitLSB bukan @d@. Nilai balik ini nantinya menentukan proses encoding maupun decding bisa dilanjutkan atau tidak.
procedure TfrmMain.Encode;
var i, j, k, x, LSBCount: Integer;
Red, Green, Blue: Integer;
strMark, bitMark, bitContent, tempContent: String;
bitRed, bitGreen, bitBlue: String;
bitBaris, bitKolom: String;
begin
try
Bmp.Assign(imgEncode.Picture.Bitmap);
Bmp.PixelFormat := pf24bit;
if CarrierCheck(Bmp) then begin
MessageDlg(�File carrier sudah disisipi data. Gunakan file yang lain�,mtWarning,[mbOK],0);
Exit;
end;LSBCount := (Bmp.Width * Bmp.Height) * 3; //menghitung jumlah total bit LSB yang bisa digunakan
LSBCount := LSBCount � (Bmp.Width * 3); // jumlah total LSB dikurangi dengan jumlah bit pada baris pixel pertama. Baris petama gambar digunakan untuk menyimpan bit penanda dan bit informasi index batas baris dan kolomtempContent := edEncodePass1.Text + �#� + moEncode.Lines.Text; //data yang akan disisipkan termasuk password dan content. Karakter # digunakan untuk memisahkan password dan content
tempContent := doEncrypt(edEncodePass1.Text, tempContent); //sebelum disisipkan data terlebih dahulu diencypt menggunakan algoritma RC4. Di sini password yang dimasukkan bertindak sebagai kunci enkripsifor i := 1 to Length(tempContent) do begin
bitContent := bitContent + getByte(Ord(tempContent[i])); //block LSB terakhir untuk menampung bit content
end;if Length(bitContent) > LSBCount then begin
MessageDlg(�Content yang akan diisikan terlalu besar.�+
#13#10+�Kurangi content atau pilih file carrier lain yang lebih besar.�,mtWarning,[mbOK],0);
Exit;
end;Self.Cursor := crHourGlass;
strMark := �@d@�; // string penanda
bitMark := getByte(Ord(strMark[1])) +
getByte(Ord(strMark[2])) +
getByte(Ord(strMark[3])); //variable bitMark digunakan untuk menampung binary strMark//Looping berikut merupakan proses penyisipan bit penanda
j := 1;
for i := 0 to 7 do begin
Red := GetRValue(GetPixel(Bmp.Canvas.Handle,i,0)); //mengambil nilai warna merah pada data pixel pada baris pertama
Green := GetGValue(GetPixel(Bmp.Canvas.Handle,i,0)); //mengambil nilai warna hijau pada data pixel pada baris pertama
Blue := GetBValue(GetPixel(Bmp.Canvas.Handle,i,0)); //mengambil nilai warna biru pada data pixel pada baris pertamabitRed := getByte(Red); //konversi nilai warna merah ke format binary
bitGreen := getByte(Green); //konversi nilai warna hijau ke format binary
bitBlue := getByte(Blue); //konversi nilai warna biru ke format binaryDelete(bitRed,8,1); //==========================================================================//
Delete(bitGreen,8,1); //hapus LSB pada setiap byte warna untuk nantinya diganti dengan bit penanda//
Delete(bitBlue,8,1); //==========================================================================//bitBlue := bitBlue + bitMark[j]; //============================================================================================================//
bitGreen := bitGreen + bitMark[j+1]; //mengganti bit LSB yang sebelumnya dihapus dengan menambahkan bit penanda berturut-turut pada akhir bit warna//
bitRed := bitRed + bitMark[j+2]; //============================================================================================================//j := j + 3; //menentukan indeks awal bit penanda pada sesi looping selanjutnyaRed := getDecimal(bitRed); //==================================================//
Green := getDecimal(bitGreen); //konversi bit binary setiap warna ke bentuk integer//
Blue := getDecimal(bitBlue); //==================================================//Bmp.Canvas.Pixels[i,0] := RGB(Red,Green,Blue);
end;k := 1;
//Looping berikut merupakan proses penyisipan bit content
for i := 1 to Bmp.Height � 1 do begin //bit content mulai disisipkan pada baris ke dua dari struktur pixel
for j := 0 to Bmp.Width � 1 do begin
Red := GetRValue(GetPixel(Bmp.Canvas.Handle,j,i)); //mengambil nilai warna merah pada data pixel pada setiap baris
Green := GetGValue(GetPixel(Bmp.Canvas.Handle,j,i)); //mengambil nilai warna hijau pada data pixel pada setiap baris
Blue := GetBValue(GetPixel(Bmp.Canvas.Handle,j,i)); //mengambil nilai warna biru pada data pixel pada setiap barisbitRed := getByte(Red); //konversi nilai warna merah ke format binary
bitGreen := getByte(Green); //konversi nilai warna hijau ke format binary
bitBlue := getByte(Blue); //konversi nilai warna biru ke format binaryDelete(bitRed,8,1); //==========================================================================//
Delete(bitGreen,8,1); //hapus LSB pada setiap byte warna untuk nantinya diganti dengan bit content//
Delete(bitBlue,8,1); //==========================================================================//bitBlue := bitBlue + bitContent[k]; //============================================================================================================//
bitGreen := bitGreen + bitContent[k+1]; //mengganti bit LSB yang sebelumnya dihapus dengan menambahkan bit content berturut-turut pada akhir bit warna//
bitRed := bitRed + bitContent[k+2]; //============================================================================================================//k := k + 3; //menentukan indeks awal bit content pada sesi looping selanjutnyaRed := getDecimal(bitRed); //==================================================//
Green := getDecimal(bitGreen); //konversi bit binary setiap warna ke bentuk integer//
Blue := getDecimal(bitBlue); //==================================================//Bmp.Canvas.Pixels[j,i] := RGB(Red,Green,Blue);
if k > length(bitContent) then Break;
end;if k > length(bitContent) then Break;
end;//block looping berikut ini digunakan untuk menyimpan informasi batas baris dan kolom yang digunakan
//untuk menyimpan content. Informasi ini nantinya digunakan sebagai acuan pada proses decoding.k := 1;
bitBaris := getWord(i); //batas indeks baris didapatkan dari nilai variable i dari hasi prosess penyisipan content di atas//Karena 8 pixel (pixel 0 sampai 7) pertama telah digunakan untuk menyimpan bit penanda,
//maka untuk bit baris dimulai dari indeks pixel ke 8.
for x := 8 to 15 do begin
//penyisipan informasi baris dimulai dari pixel ke 8 sampai 15 = 8 pixel * 3 = 24 byte
//berarti ada 24 LSB yang bisa digunakan. Tetapi karena informasi baris direpresentasikan ke dalam word (16 bit)
//maka kita hanya akan menggunakan 2 LSB (2 * 8 pixel = 16 LSB) pada setiap pixel sehingga bit baris terdestribusi secara sempurna.
//Hal ini dilakukan untuk mempermudah pada saat proses decoding.Red := GetRValue(GetPixel(Bmp.Canvas.Handle,x,0)); //mengambil nilai warna merah pada data pixel pada baris pertama
Green := GetGValue(GetPixel(Bmp.Canvas.Handle,x,0)); //mengambil nilai warna hijau pada data pixel pada baris pertama
Blue := GetBValue(GetPixel(Bmp.Canvas.Handle,x,0)); //mengambil nilai warna biru pada data pixel pada baris pertamabitRed := getByte(Red); //konversi nilai warna merah ke format binary
bitGreen := getByte(Green); //konversi nilai warna hijau ke format binaryDelete(bitRed,8,1); //==========================================================================//
Delete(bitGreen,8,1); //hapus LSB pada setiap byte warna untuk nantinya diganti dengan bit baris//bitGreen := bitGreen + bitBaris[k]; //mengganti bit LSB yang sebelumnya dihapus dengan menambahkan bit baris berturut-turut pada akhir bit warna//
bitRed := bitRed + bitBaris[k+1]; //============================================================================================================//k := k + 2; //menentukan indeks awal bit baris pada sesi looping selanjutnyaRed := getDecimal(bitRed); //==================================================//
Green := getDecimal(bitGreen); //konversi bit binary setiap warna ke bentuk integer//Bmp.Canvas.Pixels[x,0] := RGB(Red,Green,Blue);
end;k := 1;
bitKolom := getWord(j); //batas indeks kolom didapatkan dari nilai variable j dari hasi prosess penyisipan content di atas//Karena 8 pixel (pixel 8 sampai 15) kedua telah digunakan untuk menyimpan bit baris,
//maka untuk bit kolom dimulai dari indeks pixel ke 16.
for x := 16 to 23 do begin
//penyisipan informasi kolom dimulai dari pixel ke 16 sampai 23 = 8 pixel * 3 = 24 byte
//berarti ada 24 LSB yang bisa digunakan. Tetapi karena informasi kolom direpresentasikan ke dalam word (16 bit)
//maka kita hanya akan menggunakan 2 LSB (2 * 8 pixel = 16 LSB) pada setiap pixel sehingga bit baris terdestribusi secara sempurna.
//Hal ini dilakukan untuk mempermudah pada saat proses decoding.Red := GetRValue(GetPixel(Bmp.Canvas.Handle,i,0)); //mengambil nilai warna merah pada data pixel pada baris pertama
Green := GetGValue(GetPixel(Bmp.Canvas.Handle,i,0)); //mengambil nilai warna hijau pada data pixel pada baris pertama
Blue := GetBValue(GetPixel(Bmp.Canvas.Handle,i,0)); //mengambil nilai warna biru pada data pixel pada baris pertamabitRed := getByte(Red); //konversi nilai warna merah ke format binary
bitGreen := getByte(Green); //konversi nilai warna hijau ke format binaryDelete(bitRed,8,1); //==========================================================================//
Delete(bitGreen,8,1); //hapus LSB pada setiap byte warna untuk nantinya diganti dengan bit kolom//bitGreen := bitGreen + bitKolom[k]; //mengganti bit LSB yang sebelumnya dihapus dengan menambahkan bit baris berturut-turut pada akhir bit warna//
bitRed := bitRed + bitKolom[k+1]; //============================================================================================================//k := k + 2; //menentukan indeks awal bit kolom pada sesi looping selanjutnyaRed := getDecimal(bitRed); //==================================================//
Green := getDecimal(bitGreen); //konversi bit binary setiap warna ke bentuk integer//Bmp.Canvas.Pixels[x,0] := RGB(Red,Green,Blue);
end;Self.Cursor := crDefault;if MessageDlg(�Encoding telah selesai. Silahkan pilih Yes jika akan menyimpan hasil encoding.�,mtConfirmation,[mbYes,mbNo],0) = ID_YES then begin
if SavePictureDialog1.Execute then begin
SavePictureDialog1.DefaultExt := �*.bmp�;
Bmp.SaveToFile(SavePictureDialog1.FileName);
end;
end;
except
on E: Exception do begin
MessageDlg(E.Message,mtError,[mbOK],0);
end;
end;
end;
Procedure di atas digunakan untuk melakukan proses embedding/penyisipan data pesan ke file image carrier. Untuk mempermudah penjelasan, kita akan membagai badan procedure tersebut menjadi beberapa block kode program.
Bmp.Assign(imgEncode.Picture.Bitmap);
Bmp.PixelFormat := pf24bit;
if CarrierCheck(Bmp) then begin
MessageDlg(�File carrier sudah disisipi data. Gunakan file yang lain�,mtWarning,[mbOK],0);
Exit;
end;LSBCount := (Bmp.Width * Bmp.Height) * 3; //menghitung jumlah total bit LSB yang bisa digunakan
LSBCount := LSBCount � (Bmp.Width * 3); // jumlah total LSB dikurangi dengan jumlah bit pada baris pixel pertama. Baris petama gambar digunakan untuk menyimpan bit penanda dan bit informasi index batas baris dan kolomtempContent := edEncodePass1.Text + �#� + moEncode.Lines.Text; //data yang akan disisipkan termasuk password dan content. Karakter # digunakan untuk memisahkan password dan content
tempContent := doEncrypt(edEncodePass1.Text, tempContent); //sebelum disisipkan data terlebih dahulu diencypt menggunakan algoritma RC4. Di sini password yang dimasukkan bertindak sebagai kunci enkripsifor i := 1 to Length(tempContent) do begin
bitContent := bitContent + getByte(Ord(tempContent[i])); //block LSB terakhir untuk menampung bit content
end;if Length(bitContent) > LSBCount then begin
MessageDlg(�Content yang akan diisikan terlalu besar.�+
#13#10+�Kurangi content atau pilih file carrier lain yang lebih besar.�,mtWarning,[mbOK],0);
Exit;
end;Self.Cursor := crHourGlass;
strMark := �@d@�; // string penanda
bitMark := getByte(Ord(strMark[1])) +
getByte(Ord(strMark[2])) +
getByte(Ord(strMark[3])); //variable bitMark digunakan untuk menampung binary strMark
1. Langkah pertama yang dilakukan pada proses encoding adalah mencopy data bitmap dari imgEncode ke sebuah variable global Bmp kemudian mengatur format pixel Bmp menjadi 24bit, artinya akan terdapat 24 bit pada setiap pixel, hal ini perlu diperhatikan karena ketika data disisipkan program menggunakan format 8 bit untuk 1 byte warna.
2. Langkah kedua adalah mengecek apakah file bitmap bisa disisipi pesan, dengan menggunakan fungsi CarrierCheck. Jika nilai balik fungsi true, proses penyisipan akan dilanjutkan.
3. Langkah selanjutnya adalah menghitung total LSB yang bisa digunakan untuk menyisipkan data, dari hasil perhitungan ini nantinya digunakan untuk melakukan validasi apakah sebuah file bitmap mampu menampung data pesan yang diinputkan, di mana total jumlah data pesan adalah panjang password + 1 karakter pemisah (#) + panjang pesan. Jika jumlah LSB tidak mencukupi maka proses penyisipan tidak dilanjutkan.
4. Terakhir yaitu menentukan string penanda @d@ dalam bentuk biner 8 bit.
//Looping berikut merupakan proses penyisipan bit penanda
j := 1;
for i := 0 to 7 do begin
Red := GetRValue(GetPixel(Bmp.Canvas.Handle,i,0)); //mengambil nilai warna merah pada data pixel pada baris pertama
Green := GetGValue(GetPixel(Bmp.Canvas.Handle,i,0)); //mengambil nilai warna hijau pada data pixel pada baris pertama
Blue := GetBValue(GetPixel(Bmp.Canvas.Handle,i,0)); //mengambil nilai warna biru pada data pixel pada baris pertamabitRed := getByte(Red); //konversi nilai warna merah ke format binary
bitGreen := getByte(Green); //konversi nilai warna hijau ke format binary
bitBlue := getByte(Blue); //konversi nilai warna biru ke format binaryDelete(bitRed,8,1); //==========================================================================//
Delete(bitGreen,8,1); //hapus LSB pada setiap byte warna untuk nantinya diganti dengan bit penanda//
Delete(bitBlue,8,1); //==========================================================================//bitBlue := bitBlue + bitMark[j]; //============================================================================================================//
bitGreen := bitGreen + bitMark[j+1]; //mengganti bit LSB yang sebelumnya dihapus dengan menambahkan bit penanda berturut-turut pada akhir bit warna//
bitRed := bitRed + bitMark[j+2]; //============================================================================================================//j := j + 3; //menentukan indeks awal bit penanda pada sesi looping selanjutnyaRed := getDecimal(bitRed); //==================================================//
Green := getDecimal(bitGreen); //konversi bit binary setiap warna ke bentuk integer//
Blue := getDecimal(bitBlue); //==================================================//Bmp.Canvas.Pixels[i,0] := RGB(Red,Green,Blue); //penyisipan pixel
end;
Proses looping atau perulangan di atas adalah untuk menyisipkan bit-bit penanda @d@ pada 8 pixel awal (0 � 7). Tahap pertama adalah mendapatkan 3 nilai warna dasar RGB pada setiap pixel. Nilai-nilai warna dasar tersebut kemudian dikonversi ke bentuk biner 8 bit menggunakan fungsi getByte. Setelah itu bit LSB (bit paling kanan) pada setiap bit warna harus dihapus untuk nantinya digantikan oleh satu persatu bit penanda. Selanjutnya adalah mengambil 3 bit penanda pada setiap looping dan menempatkannya ke bit terakhir pada masing bit warna. Setelah didapatkan nilai bit baru kemudian dikonversi untuk membentuk nilai integer warna yang baru dan menyisipkannya ke dalam area pixel bitmap.
k := 1;
//Looping berikut merupakan proses penyisipan bit content
for i := 1 to Bmp.Height � 1 do begin //bit content mulai disisipkan pada baris ke dua dari struktur pixel
for j := 0 to Bmp.Width � 1 do begin
Red := GetRValue(GetPixel(Bmp.Canvas.Handle,j,i)); //mengambil nilai warna merah pada data pixel pada setiap baris
Green := GetGValue(GetPixel(Bmp.Canvas.Handle,j,i)); //mengambil nilai warna hijau pada data pixel pada setiap baris
Blue := GetBValue(GetPixel(Bmp.Canvas.Handle,j,i)); //mengambil nilai warna biru pada data pixel pada setiap barisbitRed := getByte(Red); //konversi nilai warna merah ke format binary
bitGreen := getByte(Green); //konversi nilai warna hijau ke format binary
bitBlue := getByte(Blue); //konversi nilai warna biru ke format binaryDelete(bitRed,8,1); //==========================================================================//
Delete(bitGreen,8,1); //hapus LSB pada setiap byte warna untuk nantinya diganti dengan bit content//
Delete(bitBlue,8,1); //==========================================================================//bitBlue := bitBlue + bitContent[k]; //============================================================================================================//
bitGreen := bitGreen + bitContent[k+1]; //mengganti bit LSB yang sebelumnya dihapus dengan menambahkan bit content berturut-turut pada akhir bit warna//
bitRed := bitRed + bitContent[k+2]; //============================================================================================================//k := k + 3; //menentukan indeks awal bit content pada sesi looping selanjutnyaRed := getDecimal(bitRed); //==================================================//
Green := getDecimal(bitGreen); //konversi bit binary setiap warna ke bentuk integer//
Blue := getDecimal(bitBlue); //==================================================//Bmp.Canvas.Pixels[j,i] := RGB(Red,Green,Blue);
if k > length(bitContent) then Break;
end;if k > length(bitContent) then Break;
end;
Kode diatas merupakan sebuah blok looping untuk menyisipkan data pesan. Proses looping disini merupakan looping bersarang untuk mendapatkan titik koordinat kolom dan baris (x, y) dari sebuah pixel. Proses penyisipan bit pesan dimulai dari baris ke 2, karena baris pertama digunakan untuk menyimpan bit penanda serta bit informasi baris dan kolom dari pixel terakhir yang digunakan untuk menyimpan bit pesan. Penyisipan data pesan atau content sebenarnya sama dengan penyisipan bit penanda, yaitu mengambil byte setiap warna, kemudian dikonversi ke 8 bit biner, menghapus bit terakhir, menambahkan bit pesan di akhir bit warna, konversi ke nilai warna berupa integer dan terakhir menyisipkan pixel baru ke wilayah pixel bitmap. Pada akhir looping program akan memeriksa apakah bit content sudah mencapai maksimal atau tidak, jika ya looping akan dihentikan. Hal ini dilakukan untuk mendapatkan nilai variable i dan j yang nantinya nilai dari kedua variable tersebut menjadi nilai koordinat baris dan kolom dari pixel terakhir yang digunakan untuk menyisipkan bit pesan. Kedua informasi tersebut (baris dan kolom) juga ikut disipkan pada pixel pertama setelah bit penanda. Dan blok kode program berikutnya merupakan proses penyisipan bit informasi baris dan kolom.
k := 1;
bitBaris := getWord(i); //batas indeks baris didapatkan dari nilai variable i dari hasi prosess penyisipan content di atas//Karena 8 pixel (pixel 0 sampai 7) pertama telah digunakan untuk menyimpan bit penanda,
//maka untuk bit baris dimulai dari indeks pixel ke 8.
for x := 8 to 15 do begin
//penyisipan informasi baris dimulai dari pixel ke 8 sampai 15 = 8 pixel * 3 = 24 byte
//berarti ada 24 LSB yang bisa digunakan. Tetapi karena informasi baris direpresentasikan ke dalam word (16 bit)
//maka kita hanya akan menggunakan 2 LSB (2 * 8 pixel = 16 LSB) pada setiap pixel sehingga bit baris terdestribusi secara sempurna.
//Hal ini dilakukan untuk mempermudah pada saat proses decoding.Red := GetRValue(GetPixel(Bmp.Canvas.Handle,x,0)); //mengambil nilai warna merah pada data pixel pada baris pertama
Green := GetGValue(GetPixel(Bmp.Canvas.Handle,x,0)); //mengambil nilai warna hijau pada data pixel pada baris pertama
Blue := GetBValue(GetPixel(Bmp.Canvas.Handle,x,0)); //mengambil nilai warna biru pada data pixel pada baris pertamabitRed := getByte(Red); //konversi nilai warna merah ke format binary
bitGreen := getByte(Green); //konversi nilai warna hijau ke format binaryDelete(bitRed,8,1); //==========================================================================//
Delete(bitGreen,8,1); //hapus LSB pada setiap byte warna untuk nantinya diganti dengan bit baris//bitGreen := bitGreen + bitBaris[k]; //mengganti bit LSB yang sebelumnya dihapus dengan menambahkan bit baris berturut-turut pada akhir bit warna//
bitRed := bitRed + bitBaris[k+1]; //============================================================================================================//k := k + 2; //menentukan indeks awal bit baris pada sesi looping selanjutnyaRed := getDecimal(bitRed); //==================================================//
Green := getDecimal(bitGreen); //konversi bit binary setiap warna ke bentuk integer//Bmp.Canvas.Pixels[x,0] := RGB(Red,Green,Blue);
end;k := 1;
bitKolom := getWord(j); //batas indeks kolom didapatkan dari nilai variable j dari hasi prosess penyisipan content di atas//Karena 8 pixel (pixel 8 sampai 15) kedua telah digunakan untuk menyimpan bit baris,
//maka untuk bit kolom dimulai dari indeks pixel ke 16.
for x := 16 to 23 do begin
//penyisipan informasi kolom dimulai dari pixel ke 16 sampai 23 = 8 pixel * 3 = 24 byte
//berarti ada 24 LSB yang bisa digunakan. Tetapi karena informasi kolom direpresentasikan ke dalam word (16 bit)
//maka kita hanya akan menggunakan 2 LSB (2 * 8 pixel = 16 LSB) pada setiap pixel sehingga bit baris terdestribusi secara sempurna.
//Hal ini dilakukan untuk mempermudah pada saat proses decoding.Red := GetRValue(GetPixel(Bmp.Canvas.Handle,i,0)); //mengambil nilai warna merah pada data pixel pada baris pertama
Green := GetGValue(GetPixel(Bmp.Canvas.Handle,i,0)); //mengambil nilai warna hijau pada data pixel pada baris pertama
Blue := GetBValue(GetPixel(Bmp.Canvas.Handle,i,0)); //mengambil nilai warna biru pada data pixel pada baris pertamabitRed := getByte(Red); //konversi nilai warna merah ke format binary
bitGreen := getByte(Green); //konversi nilai warna hijau ke format binaryDelete(bitRed,8,1); //==========================================================================//
Delete(bitGreen,8,1); //hapus LSB pada setiap byte warna untuk nantinya diganti dengan bit kolom//bitGreen := bitGreen + bitKolom[k]; //mengganti bit LSB yang sebelumnya dihapus dengan menambahkan bit baris berturut-turut pada akhir bit warna//
bitRed := bitRed + bitKolom[k+1]; //============================================================================================================//k := k + 2; //menentukan indeks awal bit kolom pada sesi looping selanjutnyaRed := getDecimal(bitRed); //==================================================//
Green := getDecimal(bitGreen); //konversi bit binary setiap warna ke bentuk integer//Bmp.Canvas.Pixels[x,0] := RGB(Red,Green,Blue);
end;
Blok kode di atas terdiri dari dua looping. Looping pertama adalah proses penyisipan bit informasi baris yang didapatkan dari nilai variable i dan looping kedua merupakan proses penyisipan bit informasi kolom, dimana nilai kolom berasal dari nilai variable j. Kedua nilai tersebut direpresentasikan ke dalam format word yakni terdiri dari 16 bit biner. Kenapa harus word atau 16 bit? Ini dikarenakan adanya kemungkinan nilai baris dan kolom lebih dari 255 sehingga tidak memungkinkan untuk menggunakan byte atau 8 bit. Urutan proses penyisipannya sama dengan penyisipan bit content maupun bit penanda, perbedaanya terletak pada jumlah LSB yang digunakan. Karena diwakili oleh 16 bit biner, maka kita harus menggunakan 2 LSB saja (LSB pada byte hijau dan merah) pada setiap pixel, dengan demikain akan dibutuhkan 8 pixel (2 * 8 = 16) untuk menampung bit baris dan kolom. Yang perlu diketahui, bit baris akan disisipkan mulai dari pixel ke 8 sampai 15 (8 pixel) dan nilai bit kolom disisipkan di pixel ke 16 sampai pixel ke 23 (8 pixel).
if MessageDlg(�Encoding telah selesai. Silahkan pilih Yes jika akan menyimpan hasil encoding.�,mtConfirmation,[mbYes,mbNo],0) = ID_YES then begin
if SavePictureDialog1.Execute then begin
SavePictureDialog1.DefaultExt := �*.bmp�;
Bmp.SaveToFile(SavePictureDialog1.FileName);
end;
end;
Blok terakhir dari badan fungsi encode merupakan proses penyimpanan file bitmap hasil proses encoding dengan terlebih dahulu menampilkan dialog konfirmasi.
Selain ada fungsi encode kita juga membutuhkan fungsi decode untuk menguraikan data pesan kembali sehingga bisa dibaca. Berikut adalah fungsi yang digunakan.
procedure TfrmMain.Decode;
var i, j, k: Integer;
Red, Green, Blue: Integer;
bitContent, tempContent: String;
bitRed, bitGreen, bitBlue: String;
bitBaris, bitKolom: String;
Baris, Kolom: Integer;
begin
try
Bmp.Assign(imgDecode.Picture.Bitmap);
Bmp.PixelFormat := pf24bit;
if not CarrierCheck(Bmp) then begin
MessageDlg(�File gambar tidak mengandung pesan.�,mtWarning,[mbOK],0);
Exit;
end;//Untuk mengambil bit content terlebih dahulu kita harus mengetahui indeks batas baris dan kolom.
//Informasi baris dan kolom diperlukan sebagai batasan pengambilan bit LSB.
//Indeks pengambilan harus sinkron dengan indeks penyisipan pada proses encoding.bitBaris := �;
for k := 8 to 15 do begin
Red := GetRValue(GetPixel(Bmp.Canvas.Handle,k,0)); //mengambil nilai warna merah pada data pixel pada baris pertama
Green := GetGValue(GetPixel(Bmp.Canvas.Handle,k,0)); //mengambil nilai warna hijau pada data pixel pada baris pertama
bitBaris := bitBaris + getByte(Green)[8] + getByte(Red)[8];
end;
Baris := getDecimal(bitBaris);bitKolom := �;
for k := 16 to 23 do begin
Red := GetRValue(GetPixel(Bmp.Canvas.Handle,k,0)); //mengambil nilai warna merah pada data pixel pada baris pertama
Green := GetGValue(GetPixel(Bmp.Canvas.Handle,k,0)); //mengambil nilai warna hijau pada data pixel pada baris pertama
bitKolom := bitKolom + getByte(Green)[8] + getByte(Red)[8];
end;
Kolom := getDecimal(bitKolom);tempContent := �;
//Looping berikut merupakan proses pengambilan bit content
for i := 1 to Bmp.Height � 1 do begin //bit content mulai diambil pada baris ke dua dari struktur pixel
for j := 0 to Bmp.Width � 1 do begin
Red := GetRValue(GetPixel(Bmp.Canvas.Handle,j,i)); //mengambil nilai warna merah pada data pixel pada setiap baris
Green := GetGValue(GetPixel(Bmp.Canvas.Handle,j,i)); //mengambil nilai warna hijau pada data pixel pada setiap baris
Blue := GetBValue(GetPixel(Bmp.Canvas.Handle,j,i)); //mengambil nilai warna biru pada data pixel pada setiap barisbitRed := getByte(Red); //konversi nilai warna merah ke format binary
bitGreen := getByte(Green); //konversi nilai warna hijau ke format binary
bitBlue := getByte(Blue); //konversi nilai warna biru ke format binarytempContent := tempContent + Copy(bitBlue,8,1) + Copy(bitGreen,8,1) + Copy(bitRed,8,1);
//mengambil LSB pada setiap byte warna dan menampunya di variable tempContentif (Baris = i) and (Kolom = j) then Break;
end;if (Baris = i) and (Kolom = j) then Break;
end;bitContent := �;
k := 1;
for i := 1 to Round(Length(tempContent)/8) do begin
//memilah setiap byte content kemudian menerjemahkannya ke dalam bentuk karakter yang bisa dibaca
bitContent := bitContent + Chr(getDecimal(Copy(tempContent,k,8)));
k := k + 8;
end;bitContent := doDecrypt(edDecodePass1.Text,bitContent); //karena karakter dienkripsi pada saat encoding, maka content harus didecript terlebih dahulu.
if edDecodePass1.Text = Copy(bitContent,1,Length(edDecodePass1.Text)) then
//eliminasi karakter password+# dari content, hingga yang tersisa karakter content untuk ditampilkan di memo.
moDecode.Lines.Text := StringReplace(bitContent,edDecodePass1.Text+�#�,�,[rfReplaceAll])
else MessageDlg(�Password yang anda masukkan salah.�,mtWarning,[mbOK],0);
except
on E: Exception do begin
MessageDlg(E.Message,mtError,[mbOK],0);
end;
end;
end;
Untuk mempermudah penjelasan, bdan fungsi akan kita bagi menjadi beberapa blok, yaitu:
Bmp.Assign(imgDecode.Picture.Bitmap);
Bmp.PixelFormat := pf24bit;
if not CarrierCheck(Bmp) then begin
MessageDlg(�File gambar tidak mengandung pesan.�,mtWarning,[mbOK],0);
Exit;
end;//Untuk mengambil bit content terlebih dahulu kita harus mengetahui indeks batas baris dan kolom.
//Informasi baris dan kolom diperlukan sebagai batasan pengambilan bit LSB.
//Indeks pengambilan harus sinkron dengan indeks penyisipan pada proses encoding.bitBaris := �;
for k := 8 to 15 do begin
Red := GetRValue(GetPixel(Bmp.Canvas.Handle,k,0)); //mengambil nilai warna merah pada data pixel pada baris pertama
Green := GetGValue(GetPixel(Bmp.Canvas.Handle,k,0)); //mengambil nilai warna hijau pada data pixel pada baris pertama
bitBaris := bitBaris + getByte(Green)[8] + getByte(Red)[8];
end;
Baris := getDecimal(bitBaris);bitKolom := �;
for k := 16 to 23 do begin
Red := GetRValue(GetPixel(Bmp.Canvas.Handle,k,0)); //mengambil nilai warna merah pada data pixel pada baris pertama
Green := GetGValue(GetPixel(Bmp.Canvas.Handle,k,0)); //mengambil nilai warna hijau pada data pixel pada baris pertama
bitKolom := bitKolom + getByte(Green)[8] + getByte(Red)[8];
end;
Kolom := getDecimal(bitKolom);
Tahap pertama adalah mengambil nilai bitmap pada image decode sebegai nilai variable Bmp, kemudian memformatnya ke dalam bitmap 24bit. Variable Bmp ini kemudian digunakan pada fungsi CarrierCheck untuk memeriksa file bitmap tersebut mengandung pesan atau tidak, jika tidak proses penguraian pesan tidak dilakukan.
Karena panjang pesan adalah acak (tidak ditentukan) maka kita harus mendapatkan nilai baris dan kolom (yang ikut dsimpan pada proses encode) terlebih dahulu. Indeks pixel dan jumlah LSB yang digunakan untuk mengambil LSB harus sama dengan proses penyisipan. Pertama nilai bit baris akan diambil mulai dari pixel ke 8 sampai pixel ke 15 dan nilai bit kolom pada pixel 16 sampai 23. Nilai kedua variable ini kemudian digunakan untuk membatasi looping pengambilan bit content. Berikutnya adalah blok program untuk mengambil bit pesan.
tempContent := �;
//Looping berikut merupakan proses pengambilan bit content
for i := 1 to Bmp.Height � 1 do begin //bit content mulai diambil pada baris ke dua dari struktur pixel
for j := 0 to Bmp.Width � 1 do begin
Red := GetRValue(GetPixel(Bmp.Canvas.Handle,j,i)); //mengambil nilai warna merah pada data pixel pada setiap baris
Green := GetGValue(GetPixel(Bmp.Canvas.Handle,j,i)); //mengambil nilai warna hijau pada data pixel pada setiap baris
Blue := GetBValue(GetPixel(Bmp.Canvas.Handle,j,i)); //mengambil nilai warna biru pada data pixel pada setiap barisbitRed := getByte(Red); //konversi nilai warna merah ke format binary
bitGreen := getByte(Green); //konversi nilai warna hijau ke format binary
bitBlue := getByte(Blue); //konversi nilai warna biru ke format binarytempContent := tempContent + Copy(bitBlue,8,1) + Copy(bitGreen,8,1) + Copy(bitRed,8,1);
//mengambil LSB pada setiap byte warna dan menampunya di variable tempContentif (Baris = i) and (Kolom = j) then Break;
end;if (Baris = i) and (Kolom = j) then Break;
end;
Pengambilan bit data pesan dimulai dari baris pixel kedua dengan terlebih dahulu mengambil byte setiap warna kemudian mengkonversinya ke bentuk string biner dan terakhir mengambil string terakhir pada setiap string biner warna (ada 3 string biner atau LSB pada satu pixel). String-string tersebut kemudian disimpan ke dalam variable tempContent. Jika indeks looping telah mencapai maksimal yakni nilai i sama dengan indeks baris maksimal dan j sama dengan indeks kolom maksimal, maka looping akan dihentikan.
String bit yang tersimpan di variable tempContent tersebut kemudian dibagi menjadi beberapa kelompok bit yang masing-masing terdiri dari 8 string bit (byte) dan setiap kelompok bit dikonversi ke bentuk AnsiChar atauWideChar dengan menggunakan fungsi Chr. Sampai di sini string pesan tersebut masih belum bisa dibaca karena masih dalam keadaan terinkripsi. Untuk itu kita harus mendekripsinya terlebih dahulu dengan password yang diinput user. Jika password benar maka kita akan mendapatkan plain teks dari string pesan tersebut. Untuk lebih amannya kita akan mengambil beberapa string awal sesuai dengan panjang password yang diinputkan user. Jika hasil perbandingan benar barulah pesan akan ditampilkan pada sebuah komponen TMemo. Berikut ini adalah blok kode program yang menggambarkan proses dekripsi pesan.
bitContent := �;
k := 1;
for i := 1 to Round(Length(tempContent)/8) do begin
//memilah setiap byte content kemudian menerjemahkannya ke dalam bentuk karakter yang bisa dibaca
bitContent := bitContent + Chr(getDecimal(Copy(tempContent,k,8)));
k := k + 8;
end;bitContent := doDecrypt(edDecodePass1.Text,bitContent); //karena karakter dienkripsi pada saat encoding, maka content harus didecript terlebih dahulu.
if edDecodePass1.Text = Copy(bitContent,1,Length(edDecodePass1.Text)) then
//eliminasi karakter password+# dari content, hingga yang tersisa karakter content untuk ditampilkan di memo.
moDecode.Lines.Text := StringReplace(bitContent,edDecodePass1.Text+�#�,�,[rfReplaceAll])
else MessageDlg(�Password yang anda masukkan salah.�,mtWarning,[mbOK],0);
Untuk mengetahui badan program lebih lengkap, silahkan downbload contoh projectnya DI SINI. Dan sebagai gambaran, berikut adalah screen shot interface programnya.
Update Contact :
No Wa/Telepon (puat) : 085267792168
No Wa/Telepon (fajar) : 085369237896
Email : Fajarudinsidik@gmail.com
No Wa/Telepon (puat) : 085267792168
No Wa/Telepon (fajar) : 085369237896
Email: Fajarudinsidik@gmail.com
atau Kirimkan Private messanger melalui email dengan klik tombol order dibawah ini :