Steganografi menggunakan Least Significant Bit (LSB) pada Java

Steganografi merupakan tehnik atau salah satu metode menyembunyikan pesan pada suatu media berupa gambar, audio maupun video sehingga pesan tersebut tidak dapat dibaca oleh pihak lain selain pemberi dan penerima pesan. Steganography berasal dari bahasa yunani yaitu steganos yang berarti tersembunyi dan graphein yang berarti menulis.

Sedangkan cryptografi merupakan tehnik menyamarkan pesan dengan cara mengacak atau merubahnya kedalam bentuk tertentu.

Media

Adapun media-media yang dapat dipakai dalam menyembunyikan pesan (steganografi) adalah:

  • Format image : bitmap (bmp), gif, pcx, jpeg, dll.
  • Format audio : wav, voc, mp3, dll.
  • Format video : avi, mpeg dll
  • Format lain : teks file, html, pdf, dll.

Metode

Sedangkan metode steganografi terdiri dari:

  • Least Significant Bit (LSB)
  • Algorithem and Transformation
  • Redundant Pattren Encoding
  • Spread Spectrum Methode
  • Steganalisis and Stegosystem

Pesan yang tersimpan pada sebuah media penympanan sebelum disimpan atau disembunyikan dapat di encrypt terlebih dahulu menggunakan algoritma encryption seperti ciphertext viginare, ciphertext caisar, MD5, RSA dll. Sehingga pesan menjadi benar-benar rahasia karena menggabungkan kedua metode yaitu Cryptografi dan Steganografi.

Pada kesempatan kali ini, sedikit akan mengulas mengenai bagaimana menyembunyikan pesan atau Steganografi menggunakan Least Significant Bit (LSB) dengan metode encripsi menggunakan algoritma Ciphertext Viginare pada media penyimpanan berupa gambar / image. Bahasa pemrograman yang digunakan kali ini adalah menggunakan bahasa pemrograman Java.

OK langsung aja berikut penjelasan singkat mengenai Steganografi Menggunakan Least significant Bit (LSB):

1. Class Image_Filter.java

Class ini digunakan untuk menyaring media penyimpanan yang akan dipakai, dalam hal ini gambar yang dapat digunakan adalah gambar yang berextensi .jpg dan .png

[code lang=”java”]
package stegano.gun;

/*
*Import List
*/
import java.io.*;

/*
*Image_Filter Class
*/
public class Image_Filter extends javax.swing.filechooser.FileFilter
{

protected boolean isImageFile(String ext)
{
return (ext.equals(“jpg”)||ext.equals(“png”));
}

public boolean accept(File f)
{
if (f.isDirectory())
{
return true;
}

String extension = getExtension(f);
if (extension.equals(“jpg”)||extension.equals(“png”))
{
return true;
}
return false;
}

public String getDescription()
{
return “Supported Image Files”;
}

protected static String getExtension(File f)
{
String s = f.getName();
int i = s.lastIndexOf(‘.’);
if (i > 0 && i < s.length() – 1)
return s.substring(i+1).toLowerCase();
return “”;
}
}
[/code]

2. Class ViginareCipher.java
Class ini digunakan untuk meng-encrypt text yang akan disimpan ke dalam media penyimpanan.

[code lang=”java”]

package stegano.gun;

import java.util.Vector;

public class VigenereCipher {
private static final char[] alphnum = {
‘A’, ‘B’, ‘C’, ‘D’, ‘E’, ‘F’, ‘G’, ‘H’, ‘I’, ‘J’, ‘K’, ‘L’,
‘M’, ‘N’, ‘O’, ‘P’, ‘Q’, ‘R’, ‘S’, ‘T’, ‘U’, ‘V’, ‘W’, ‘X’,
‘Y’, ‘Z’, ‘0’, ‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’,
‘@’,’?’,’#’,’-‘,’+’,’!’,’$’,’%’,’&’,’*’,'(‘,’)’,’_’,’+’,’=’,
‘.’,’,’,’;’,’:’,'”‘,’\”,’}’,'{‘,’\\’,’/’,’^’,'<‘,’>’,'[‘,’]’,
‘^’,’|’,’`’,’~’
};

private static final int dim = alphnum.length;
private char[][] vgnrSquare = new char[alphnum.length][alphnum.length];
private Vector<Character> alphnumv = new Vector<Character>();

public VigenereCipher() {
init();

/* copy contents of alphum array to alphnumv vector to exploit indexOf method */
for(int i = 0; i < dim; i++) {
alphnumv.add(alphnum[i]);
}

print();
}

/**
* Initializes the contents of the Vigenere Square using the given alphanumeric set.
*/
public void init() {
/* Fill up the upper left triangle */
for(int i = 0; i < dim; i++) {
for(int j = i; j < dim; j++) {
if(i == 0) {
vgnrSquare[i][j] = alphnum[j];
} else {
vgnrSquare[i][j-i] = alphnum[j];
}
}
}

/* Fill up the remaining cells */
for(int i = 1; i < dim; i++) {
int k = 0; // always start from the first element of the set

for(int j = dim-i; j < dim; j++) {
vgnrSquare[i][j] = alphnum[k];
k++;
}
}
}

/**
* Encrypts the given plaintext using the specified key.
* @param plaintext the text to be encrypted
* @param key the encryption key
*/
public String encrypt(String plaintext, String key) {
if(keyHasSpace(key) || key.length() == 0) {
System.out.println(“\nKey cannot contain a space!\n”);
return null;
} else if(plaintext.length() == 0) {
System.out.println(“\nNothing to encrypt!\n”);
return null;
} else {
char[] ciphertext = new char[plaintext.length()];
key = generateKey(plaintext, key); // update key

for(int i = 0; i < ciphertext.length; i++) {
int row = alphnumv.indexOf(Character.toUpperCase(key.charAt(i)));
int col = alphnumv.indexOf(Character.toUpperCase(plaintext.charAt(i)));

if(plaintext.charAt(i) == ‘ ‘) {
ciphertext[i] = ‘ ‘;
} else if(plaintext.charAt(i) == ‘\n’) {
ciphertext[i] = ‘\n’;
} else if(plaintext.charAt(i) == ‘\t’) {
ciphertext[i] = ‘\t’;
} else{
ciphertext[i] = vgnrSquare[row][col]; // encryption

/* retain case
if(Character.isLowerCase(plaintext.charAt(i))) {
ciphertext[i] = Character.toLowerCase(ciphertext[i]);
}*/
}
}

System.out.println(“\nPlaintext: ” + plaintext);
System.out.println(“Key: ” + key);
return (new String(ciphertext));
}
}

/**
* Decrypts the given ciphertext using the specified key.
* @param ciphertext the text to be decrypted
* @param key the decryption key
*/
public String decrypt(String ciphertext, String key) {
if(keyHasSpace(key) || key.length() == 0) {
System.out.println(“\nKey cannot contain a space!\n”);
return null;
} else if(ciphertext.length() == 0) {
System.out.println(“\nNothing to decrypt!\n”);
return null;
} else {

char[] plaintext = new char[ciphertext.length()];
key = generateKey(ciphertext, key); // update key

for(int i = 0; i < plaintext.length; i++) {
int row = alphnumv.indexOf(Character.toUpperCase(key.charAt(i)));
int col = alphnumv.indexOf(Character.toUpperCase(ciphertext.charAt(i)));

if(ciphertext.charAt(i) == ‘ ‘) {
plaintext[i] = ‘ ‘;
} else if(ciphertext.charAt(i) == ‘\n’) {
plaintext[i] = ‘\n’;
} else if(ciphertext.charAt(i) == ‘\t’) {
plaintext[i] = ‘\t’;
}else{
int x = (col – row) % dim; // decryption algebraic approach

if(x >= 0) {
plaintext[i] = alphnumv.elementAt(x).toString().charAt(0);
} else {
plaintext[i] = alphnumv.elementAt(dim+x).toString().charAt(0);
}

/* retain case
if(Character.isLowerCase(ciphertext.charAt(i))) {*/
plaintext[i] = Character.toLowerCase(plaintext[i]);
//}
}
}

System.out.println(“\nCiphertext: ” + ciphertext);
System.out.println(“Key: ” + key);
return (new String(plaintext));
}
}

/**
* Generates the repeating key.
* @param text the plaintext/ciphertext which serves as the basis for the key’s length
* @param key the initial, non-repeating key
* @return newKey – the new (repeating) key
*/
public String generateKey(String text, String key) {
char[] newKey = new char[text.length()];
int repeatFlag = 0;

for(int i = 0; i < newKey.length; i++) {
if(text.charAt(i) == ‘ ‘) {
newKey[i] = ‘ ‘;
} else {
newKey[i] = key.charAt(repeatFlag);

if(repeatFlag+1 == key.length()) {
repeatFlag = 0;
} else {
repeatFlag++;
}
}
}

return new String(newKey);
}

/**
* Checks whether the inputted key contains a space.
* @param key the key to be scanned
* @return answer – boolean value
*/
public boolean keyHasSpace(String key) {
boolean answer = false;

for(int i = 0; i < key.length(); i++) {
if(key.charAt(i) == ‘ ‘) {
answer = true;
break;
}
}

return answer;
}

/**
* Prints the Vigenere Square.
*/
public void print() {
System.out.println();

for(int i = 0; i < dim; i++) {
for(int j = 0; j < dim; j++) {
System.out.print(vgnrSquare[i][j] + ” “);

if(j == dim-1) {
System.out.println();
}
}
}
}

}
[/code]

3. Class Steganography.java
Class ini digunakan untuk menyisipkan pesan pada gambar menggunakan metode Least Significant Bit (LSB)

[code lang=”java”]
package stegano.gun;

import java.io.File;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.awt.image.DataBufferByte;

import javax.imageio.ImageIO;
import javax.swing.JOptionPane;

public class Steganography
{

public Steganography()
{
}

public String encrypt(String text, String key){
char[] karakter=text.toCharArray();
String cipherText=””;
for(int j=0;j<karakter.length;j++){
key+=j+2;
}
for(int i=0;i<karakter.length;i++){
cipherText+=(char)(((128+(karakter[i])+(key.charAt(i)))%128));
}
return cipherText;
}

public String Decrypt(String text, String key1){

char[] karakter=text.toCharArray();
String cipherText=””;
for(int j=0;j<karakter.length;j++){
key1+=j+2;
}
for(int i=0;i<karakter.length;i++){
cipherText+=(char)(((128+(karakter[i])-(key1.charAt(i)))%128));

}
return cipherText;
}

public boolean encode(String path, String original, String ext1, String stegan, String message)
{
String file_name = image_path(path,original,ext1);
BufferedImage image_orig = getImage(file_name);

//user space is not necessary for Encrypting
BufferedImage image = user_space(image_orig);
image = add_text(image,message);

return(setImage(image,new File(image_path(path,stegan,”png”)),”png”));
}

public String decode(String path, String name)
{
byte[] decode;
try
{
//user space is necessary for decrypting
BufferedImage image = user_space(getImage(image_path(path,name,”png”)));
decode = decode_text(get_byte_data(image));
return(new String(decode));
}
catch(Exception e)
{
JOptionPane.showMessageDialog(null,
“Tidak ada pesan yang tersembunyi di dalam gambar yang dipilih”,”Error”,
JOptionPane.ERROR_MESSAGE);
return “”;
}
}

private String image_path(String path, String name, String ext)
{
return path + “/” + name + “.” + ext;
}

private BufferedImage getImage(String f)
{
BufferedImage image = null;
File file = new File(f);

try
{
image = ImageIO.read(file);
}
catch(Exception ex)
{
JOptionPane.showMessageDialog(null,
“Gambar Tidak dapat Dibaca!”,”Error”,JOptionPane.ERROR_MESSAGE);
}
return image;
}
private boolean setImage(BufferedImage image, File file, String ext)
{
try
{
file.delete(); //delete resources used by the File
ImageIO.write(image,ext,file);
return true;
}
catch(Exception e)
{
JOptionPane.showMessageDialog(null,
“Gambar Tidak dapat Disimpan!”,”Error”,JOptionPane.ERROR_MESSAGE);
return false;
}
}

private BufferedImage add_text(BufferedImage image, String text)
{
//convert all items to byte arrays: image, message, message length
byte img[] = get_byte_data(image);
byte msg[] = text.getBytes();
byte len[] = bit_conversion(msg.length);
try
{
encode_text(img, len, 0); //0 first positiong
encode_text(img, msg, 32); //4 bytes of space for length: 4bytes*8bit = 32 bits
}
catch(Exception e)
{
JOptionPane.showMessageDialog(null,
“Target File cannot hold message!”, “Error”,JOptionPane.ERROR_MESSAGE);
}
return image;
}

private BufferedImage user_space(BufferedImage image)
{
//create new_img with the attributes of image
BufferedImage new_img = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
Graphics2D graphics = new_img.createGraphics();
graphics.drawRenderedImage(image, null);
graphics.dispose(); //release all allocated memory for this image
return new_img;
}

private byte[] get_byte_data(BufferedImage image)
{
WritableRaster raster = image.getRaster();
DataBufferByte buffer = (DataBufferByte)raster.getDataBuffer();
return buffer.getData();
}
private byte[] bit_conversion(int i)
{
//originally integers (ints) cast into bytes
//byte byte7 = (byte)((i & 0xFF00000000000000L) >>> 56);
//byte byte6 = (byte)((i & 0x00FF000000000000L) >>> 48);
//byte byte5 = (byte)((i & 0x0000FF0000000000L) >>> 40);
//byte byte4 = (byte)((i & 0x000000FF00000000L) >>> 32);

//only using 4 bytes
byte byte3 = (byte)((i & 0xFF000000) >>> 24); //0
byte byte2 = (byte)((i & 0x00FF0000) >>> 16); //0
byte byte1 = (byte)((i & 0x0000FF00) >>> 8 ); //0
byte byte0 = (byte)((i & 0x000000FF) );
//{0,0,0,byte0} is equivalent, since all shifts >=8 will be 0
return(new byte[]{byte3,byte2,byte1,byte0});
}

private byte[] encode_text(byte[] image, byte[] addition, int offset)
{
//check that the data + offset will fit in the image
if(addition.length + offset > image.length)
{
throw new IllegalArgumentException(“File not long enough!”);
}
//loop through each addition byte
for(int i=0; i<addition.length; ++i)
{
//loop through the 8 bits of each byte
int add = addition[i];
for(int bit=7; bit>=0; –bit, ++offset) //ensure the new offset value carries on through both loops
{
//assign an integer to b, shifted by bit spaces AND 1
//a single bit of the current byte
int b = (add >>> bit) & 1;
//assign the bit by taking: [(previous byte value) AND 0xfe] OR bit to add
//changes the last bit of the byte in the image to be the bit of addition
image[offset] = (byte)((image[offset] & 0xFE) | b );
}
}
return image;
}

private byte[] decode_text(byte[] image)
{
int length = 0;
int offset = 32;
//loop through 32 bytes of data to determine text length
for(int i=0; i<32; ++i) //i=24 will also work, as only the 4th byte contains real data
{
length = (length << 1) | (image[i] & 1);
}

byte[] result = new byte[length];

//loop through each byte of text
for(int b=0; b<result.length; ++b )
{
//loop through each bit within a byte of text
for(int i=0; i<8; ++i, ++offset)
{
//assign bit: [(new byte value) << 1] OR [(text byte) AND 1]
result[b] = (byte)((result[b] << 1) | (image[offset] & 1));
}
}
return result;
}
}
[/code]

4. Desain Halaman Encode dan Halaman Decode
Berikut Desain Halaman Encode:
encode

Berikut Desain Halaman Decode:
decode

Hasil Uji Coba Encode :
hasil1

Uji Coba Decode:
hasil2

Download Aplikasi Steganografi versi 1.0 (JSteg v1.0)

Related Post

Penggunaan DateTimePicker pada Java DateTimePicker merupakan komponen yang dapat digunakan untuk memilih tanggal. salah satu contoh penggunaan datetimepicker pada java adalah form input ...
MSID Sales (Sistem Penjualan Door to Door) MSID Sales atau Mataram Software-Id sales merupakan aplikasi yang digunakan untuk mengelola sistem penjualan door to door atau sistem ngampas. FItur ...
Tutorial Java Swing Implementasi MVC Dengan Databa... Pada tutorial java swing kali ini, akan dijelaskan bagaimana implementasi MVC (Model View Controller) pada Java dengan database Microsoft Access 2016....
Membuat Laporan Menggunakan IReport 5.5.0 dengan D... Pada tutorial sebelumnya tentang: Tutorial Java Swing Implementasi MVC Dengan Database Ms. Access 2016 Part 1 Tutorial Java Swing Implementasi MVC D...
Software Akuntansi MSID Accounting Pro Aplikasi atau Software Akuntansi MSID Accounting Pro merupakan aplikasi akuntansi dan keuangan yang digunakan untuk membuat laporan keuangan perusahaa...
Aplikasi Manajemen Hotel (MSIDHotel V2.0) Aplikasi MSIDHotel v2.0 merupakan Aplikasi manajemen hotel atau bungalows untuk manajemen tamu hotel mulai dari proses reservasi sampai proses check o...
Membuat Class DBConnection pada Java menggunakan N... Pada tutorial ini menjelaskan tentang cara membuat class  DBConnection pada java menggunakan netbeans untuk melakukan koneksi ke database MySQL maupun...
Java : Membuat Laporan Menggunakan IReport 5.5.0 Hal yang paling vital dalam membuat sistem informasi adalah pembuatan laporan. Membuat laporan merupakan hal yang paling melelahkan apa lagi terdiri d...
Java membuat Validasi Form Input Pada tutorial Java Membuat Validasi Form Input kali ini kita akan mencoba membuat aplikasi sederhana untuk membatasi karakter yang boleh di masukan pa...
Cara Install IReport Plugin untuk Netbeans Saat kita membangun sebuah sistem berupa aplikasi desktop menggunakan Java tentu membuat report atau laporan adalah hal yang wajib. Membuat laporan pa...

10 tanggapan untuk “Steganografi menggunakan Least Significant Bit (LSB) pada Java

  1. Riz Balas

    terimakasih programnya berjalan dengan lancar, apakah format file txt nya bisa dirubah jadi file dokumen ga mas ? semisal docx, xlsx, pdf dll itu source codenya diganti gimana ya?

  2. sam Balas

    Mas, bisa minta tolong dishare untuk source code dari fungsi-fungsi buttonnya?
    Terimakasih banyak

  3. amin Balas

    mas seandainya klau untuk menyembunyikan folder yg berisikan data di audio,dan pada saat di decode bisa gak mas folder tersebut di simpan kembali.dan audio yg berisikann data di hapus.
    “kluarga java”

  4. Na'diena Balas

    trimakasih artikel nya, izin copas ya buat tugas kampus.hehehehehe

  5. oni Balas

    sya coba di netbeans kog gak bisa yah? boleh minta project.nya g gan?

Tinggalkan Balasan

Alamat email Anda tidak akan dipublikasikan. Ruas yang wajib ditandai *

two + three =