Steganografi dina GIF

perkenalan

salam.
Teu lami pisan, nalika kuring nuju diajar di universitas, aya kursus dina disiplin "Metode parangkat lunak kaamanan inpormasi." Tugasna ngabutuhkeun kami pikeun nyiptakeun program anu nyelapkeun pesen dina file GIF. Kuring mutuskeun pikeun ngalakukeunana di Jawa.

Dina artikel ieu kuring bakal ngajelaskeun sababaraha titik teoritis, kitu ogé kumaha program leutik ieu dijieun.

Bagian téoritis

format GIF

GIF (Graphics Interchange Format - format pikeun tukeur gambar) nyaéta format pikeun nyimpen gambar grafis, sanggup nyimpen data anu dikomprés tanpa kaleungitan kualitas dina format dugi ka 256 warna. Format ieu dikembangkeun dina 1987 (GIF87a) ku CompuServe pikeun ngirimkeun gambar raster ngaliwatan jaringan. Taun 1989, formatna dirobih (GIF89a), dukungan pikeun transparansi sareng animasi ditambahkeun.

File GIF ngagaduhan struktur blok. blok ieu salawasna boga panjang tetep (atawa eta gumantung kana sababaraha umbul), jadi éta ampir teu mungkin keur nyieun kasalahan ngeunaan dimana unggal blok lokasina. Struktur gambar GIF non-animasi pangbasajanna dina format GIF89a:

Steganografi dina GIF

Tina sadaya blok struktur, dina hal ieu urang bakal resep kana blok palette global sareng parameter anu tanggung jawab pikeun palette:

  • CT - ayana palette global. Lamun bandéra ieu disetel, palette global kudu dimimitian langsung saatos cecekelan layar logis.
  • Size - Ukuran palette sareng jumlah warna dina gambar. Nilai pikeun parameter ieu:

ukuran
Jumlah kelir
Ukuran palet, bait

7
256
768

6
128
384

5
64
192

4
32
96

3
16
48

2
8
24

1
4
12

0
2
6

Métode énkripsi

Métode di handap ieu bakal dianggo pikeun énkripsi pesen dina file gambar:

  • métode LSB (Least Significant Bit).
  • Métode tambahan palette

métode LSB - métode umum tina steganography. Ieu diwangun ku ngaganti bit signifikan panungtungan dina wadahna (dina hal urang, bait palette global) jeung bit pesen disumputkeun.

Program bakal ngagunakeun dua bit panungtungan dina bait palette global salaku bagian tina metoda ieu. Ieu ngandung harti yén pikeun gambar 24-bit, dimana palette warna tilu bait pikeun beureum, biru, jeung héjo, sanggeus embedding pesen kana eta, unggal komponén warna bakal robah ku maksimum 3/255 gradasi. Parobihan sapertos kitu, mimitina, bakal teu katingali atanapi sesah ditingali ku panon manusa, sareng kadua, éta moal katingali dina alat kaluaran inpormasi kualitas rendah.

Jumlah inpormasi bakal langsung gumantung kana ukuran palette gambar. Kusabab ukuran maksimum palette nyaeta 256 kelir, sarta lamun dua bit pesen ditulis kana komponén unggal warna, panjang pesen maksimum (kalawan palette maksimum dina gambar) nyaeta 192 bait. Sakali pesen dipasang dina gambar, ukuran file henteu robih.

Métode ékspansi palette, nu ngan lumaku pikeun struktur GIF. Éta bakal paling efektif dina gambar sareng palette leutik. Intina nyaéta yén éta ningkatkeun ukuran palette, ku kituna nyayogikeun rohangan tambahan pikeun nyerat bait anu dipikabutuh pikeun ngagantikeun bait warna. Upami urang nganggap yén ukuran minimum palette nyaéta 2 warna (6 bait), maka ukuran maksimal pesen anu dipasang tiasa 256 × 3–6 = 762 bait. Karugianna nyaéta kaamanan kriptografi anu rendah; pesen anu diselapkeun tiasa dibaca nganggo pangropéa téksu mana waé upami pesen éta henteu acan ngalaman énkripsi tambahan.

Bagian praktis

Desain program

Sadaya alat anu dipikabutuh pikeun ngalaksanakeun algoritma enkripsi sareng dekripsi bakal dilebetkeun kana bungkusan com.tsarik.steganography. Paket ieu kalebet antarmuka Encryptor kalawan métode encrypt и decrypt, Kelas Binary, nu nyadiakeun kamampuhan pikeun digawekeun ku arrays bit, kitu ogé kelas iwal UnableToEncryptException и UnableToDecryptException, anu kedah dianggo dina metode antarmuka Encryptor bisi kasalahan encoding jeung decoding masing-masing.

Paket program utama com.tsarik.programs.gifed bakal kaasup kelas program runnable kalawan metoda statik main, ngidinan Anjeun pikeun ngajalankeun program; kelas nu nyimpen parameter program; jeung bungkusan jeung kelas séjén.

Palaksanaan algoritma sorangan bakal dibere dina bungkusan com.tsarik.programs.gifed.gif kelas GIFEncryptorByLSBMethod и GIFEncryptorByPaletteExtensionMethod. Duanana kelas ieu bakal nerapkeun panganteur Encryptor.

Dumasar kana struktur format GIF, anjeun tiasa nyiptakeun algoritma umum pikeun ngenalkeun pesen kana palette gambar:

Steganografi dina GIF

Pikeun nangtukeun ayana pesen dina gambar, perlu pikeun nambahkeun runtuyan bit tangtu ka awal pesen, nu decoder nu maca munggaran tur mariksa correctness. Upami éta henteu cocog, maka éta dianggap henteu aya pesen anu disumputkeun dina gambar. Satuluyna anjeun kudu nangtukeun panjang suratna. Lajeng téks pesen sorangan.

Diagram kelas tina sakabéh aplikasi:

Steganografi dina GIF

Palaksanaan program

Palaksanaan sakabéh program bisa dibagi jadi dua komponén: palaksanaan enkripsi interface jeung métode dekripsi Encryptor, di kelas GIFEncryptorByLSBMethod и GIFEncryptorByPaletteExtensionMethod, jeung palaksanaan antarbeungeut pamaké.

Mertimbangkeun kelas GIFEncryptorByLSBMethod.

Steganografi dina GIF

widang firstLSBit и secondLSBit ngandung jumlah bit unggal bait gambar nu pesen kudu diasupkeun jeung ti mana pesen kudu dibaca. Sawah checkSequence nyimpen runtuyan bit cek pikeun mastikeun pangakuan pesen embedded. Métode statik getEncryptingFileParameters mulih parameter tina file dieusian jeung karakteristik pesen poténsial.

Algoritma métode encrypt класса GIFEncryptorByLSBMethod:

Steganografi dina GIF

Sareng kode na:

@Override
public void encrypt(File in, File out, String text) throws UnableToEncodeException, NullPointerException, IOException {
	if (in == null) {
		throw new NullPointerException("Input file is null");
	}
	if (out == null) {
		throw new NullPointerException("Output file is null");
	}
	if (text == null) {
		throw new NullPointerException("Text is null");
	}
	
	// read bytes from input file
	byte[] bytes = new byte[(int)in.length()];
	InputStream is = new FileInputStream(in);
	is.read(bytes);
	is.close();
	
	// check format
	if (!(new String(bytes, 0, 6)).equals("GIF89a")) {
		throw new UnableToEncodeException("Input file has wrong GIF format");
	}
	
	// read palette size property from first three bits in the 10-th byte from the file
	byte[] b10 = Binary.toBitArray(bytes[10]);
	byte bsize = Binary.toByte(new byte[] {b10[0], b10[1], b10[2]});
	
	// calculate color count and possible message length
	int bOrigColorCount = (int)Math.pow(2, bsize+1);
	int possibleMessageLength = bOrigColorCount*3/4;
	int possibleTextLength = possibleMessageLength-2;// one byte for check and one byte for message length
	
	if (possibleTextLength < text.length()) {
		throw new UnableToEncodeException("Text is too big");
	}
	
	int n = 13;
	
	// write check sequence
	for (int i = 0; i < checkSequence.length/2; i++) {
		byte[] ba = Binary.toBitArray(bytes[n]);
		ba[firstLSBit] = checkSequence[2*i];
		ba[secondLSBit] = checkSequence[2*i+1];
		bytes[n] = Binary.toByte(ba);
		n++;
	}
	
	// write text length
	byte[] cl = Binary.toBitArray((byte)text.length());
	for (int i = 0; i < cl.length/2; i++) {
		byte[] ba = Binary.toBitArray(bytes[n]);
		ba[firstLSBit] = cl[2*i];
		ba[secondLSBit] = cl[2*i+1];
		bytes[n] = Binary.toByte(ba);
		n++;
	}
	
	// write message
	byte[] textBytes = text.getBytes();
	for (int i = 0; i < textBytes.length; i++) {
		byte[] c = Binary.toBitArray(textBytes[i]);
		for (int ci = 0; ci < c.length/2; ci++) {
			byte[] ba = Binary.toBitArray(bytes[n]);
			ba[firstLSBit] = c[2*ci];
			ba[secondLSBit] = c[2*ci+1];
			bytes[n] = Binary.toByte(ba);
			n++;
		}
	}
	
	// write output file
	OutputStream os = new FileOutputStream(out);
	os.write(bytes);
	os.close();
}

Algoritma jeung kode sumber métode decrypt класса GIFEncryptorByLSBMethod:

Steganografi dina GIF

@Override
public String decrypt(File in) throws UnableToDecodeException, NullPointerException, IOException {
	if (in == null) {
		throw new NullPointerException("Input file is null");
	}
	
	// read bytes from input file
	byte[] bytes = new byte[(int)in.length()];
	InputStream is = new FileInputStream(in);
	is.read(bytes);
	is.close();
	
	// check format
	if (!(new String(bytes, 0, 6)).equals("GIF89a")) {
		throw new UnableToDecodeException("Input file has wrong GIF format");
	}
	
	// read palette size property from first three bits in the 10-th byte from the file
	byte[] b10 = Binary.toBitArray(bytes[10]);
	byte bsize = Binary.toByte(new byte[] {b10[0], b10[1], b10[2]});
	
	// calculate color count and possible message length
	int bOrigColorCount = (int)Math.pow(2, bsize+1);
	int possibleMessageLength = bOrigColorCount*3/4;
	int possibleTextLength = possibleMessageLength-2;	// one byte for check and one byte for message length
	
	int n = 13;
	
	// read check sequence
	byte[] csBits = new byte[checkSequence.length];
	for (int i = 0; i < 4; i++) {
		byte[] ba = Binary.toBitArray(bytes[n]);
		csBits[2*i] = ba[firstLSBit];
		csBits[2*i+1] = ba[secondLSBit];
		n++;
	}
	byte cs = Binary.toByte(csBits);
	
	if (cs != Binary.toByte(checkSequence)) {
		throw new UnableToDecodeException("There is no encrypted message in the image (Check sequence is incorrect)");
	}
	
	// read text length
	byte[] cl = new byte[8];
	for (int i = 0; i < 4; i++) {
		byte[] ba = Binary.toBitArray(bytes[n]);
		cl[2*i] = ba[firstLSBit];
		cl[2*i+1] = ba[secondLSBit];
		n++;
	}
	byte textLength = Binary.toByte(cl);
	
	if (textLength < 0) {
		throw new UnableToDecodeException("Decoded text length is less than 0");
	}
	if (possibleTextLength < textLength) {
		throw new UnableToDecodeException("There is no messages (Decoded message length (" + textLength + ") is less than Possible message length (" + possibleTextLength + "))");
	}
	
	// read text bits and make text bytes
	byte[] bt = new byte[textLength];
	for (int i = 0; i < bt.length; i++) {
		byte[] bc = new byte[8];
		for (int bci = 0; bci < bc.length/2; bci++) {
			byte[] ba = Binary.toBitArray(bytes[n]);
			bc[2*bci] = ba[firstLSBit];
			bc[2*bci+1] = ba[secondLSBit];
			n++;
		}
		bt[i] = Binary.toByte(bc);
	}
	
	return new String(bt);
}

Palaksanaan kelas GIFEncryptorByPaletteExtensionMethod bakal sarupa, ngan cara nyimpen / maca informasi béda.

Di kelas MainFrame métode wrapper digambarkeun: encryptImage(Encryptor encryptor) и decryptImage(Encryptor encryptor), ngolah hasil métode panganteur Encryptor sareng interaksi sareng pangguna, nyaéta muka dialog pilihan file, nunjukkeun pesen kasalahan, jsb.; kitu ogé métode séjénna: openImage(), ngamungkinkeun pamaké pikeun milih hiji gambar, exit(), anu kaluar tina aplikasi. Métode ieu disebut ti Action's item menu pakait. Kelas ieu ogé nerapkeun metode bantu: createComponents() - nyiptakeun komponén bentuk, loadImageFile(File f) - ngamuat gambar kana komponén khusus tina file. Palaksanaan kelas GIFEncryptorByPaletteExtensionMethod sarupa jeung palaksanaan kelas GIFEncryptorByLSBMethod, Beda utama nyaéta dina cara bait pesen anu ditulis sareng dibaca tina palette.

Operasi program

Métode LBS

Hayu urang nyebutkeun aya gambar kawas kieu:

Steganografi dina GIF

Dina gambar ieu, palette diwangun ku 256 kelir (sakumaha cet ngahemat). Opat warna kahiji nyaéta: bodas, hideung, beureum, héjo. kelir séjén hideung. Urutan bit palette global bakal kieu:

11111111 11111111 11111111 00000000 00000000 00000000 11111111 00000000 00000000 00000000 11111111 00000000...

Steganografi dina GIF

Sakali pesen dipasang, bit anu digariskeun bakal diganti ku bit tina pesen. Gambar anu dihasilkeun ampir teu béda ti aslina.

asli
Gambar sareng pesen anu dipasang

Steganografi dina GIF
Steganografi dina GIF

Métode ékspansi palette

Nalika anjeun muka gambar anu ngandung pesen nganggo metode ieu, anjeun bakal ningali gambar ieu:

Steganografi dina GIF

Ieu jelas yén métode ieu moal bisa dipaké pikeun kagiatan spionase full-fledged, sarta bisa merlukeun enkripsi tambahan suratna.

Énkripsi / dekripsi dina gambar animasi jalanna sapertos dina gambar statik biasa, tapi animasina henteu rusak.

Sumber anu digunakeun:

Undeur:

sumber: www.habr.com

Tambahkeun komentar