Стеганография дар GIF

Муқаддима

Салом.
Чанде пеш, вақте ки ман дар донишгоҳ таҳсил мекардам, аз фанни «Усулҳои нармафзори амнияти иттилоотӣ» кори курсӣ буд. Супориш аз мо талаб мекард, ки барномаеро созем, ки паёмро дар файлҳои GIF ҷойгир кунад. Ман қарор додам, ки онро дар Java иҷро кунам.

Дар ин мақола ман баъзе нуктаҳои назариявиро тавсиф мекунам, инчунин чӣ гуна ин барномаи хурд сохта шудааст.

Қисми назариявӣ

Формати GIF

GIF (Graphics Interchange Format - формати мубодилаи тасвирҳо) форматест барои нигоҳдории тасвирҳои графикӣ, ки қодир аст маълумоти фишурдашударо бидуни гум кардани сифат дар формати то 256 ранг нигоҳ дорад. Ин формат соли 1987 (GIF87a) аз ҷониби CompuServe барои интиқоли тасвирҳои растрӣ тавассути шабакаҳо таҳия шудааст. Дар соли 1989 формат тағир дода шуд (GIF89a), дастгирии шаффофият ва аниматсия илова карда шуд.

Файлҳои GIF дорои сохтори блок мебошанд. Ин блокҳо ҳамеша дарозии собит доранд (ё он аз баъзе парчамҳо вобаста аст), бинобар ин дар бораи ҷойгиршавии ҳар як блок хато кардан қариб ғайриимкон аст. Сохтори соддатарин тасвири аниматсионии GIF дар формати GIF89a:

Стеганография дар GIF

Аз ҳамаи блокҳои сохтор, дар ин ҳолат мо ба блоки палитраи глобалӣ ва параметрҳое, ки барои палитра масъуланд, таваҷҷӯҳ хоҳем кард:

  • CT — мавҷудияти палитраи глобалӣ. Агар ин парчам гузошта шуда бошад, палитраи глобалӣ бояд фавран пас аз дастаки экрани мантиқӣ оғоз шавад.
  • Size — андозаи палитра ва шумораи рангҳои расм. Арзишҳо барои ин параметр:

андоза
Шумораи рангҳо
Андозаи палитра, байт

7
256
768

6
128
384

5
64
192

4
32
96

3
16
48

2
8
24

1
4
12

0
2
6

Усулҳои рамзгузорӣ

Барои рамзгузории паёмҳо дар файлҳои тасвирӣ усулҳои зерин истифода мешаванд:

  • Усули LSB (камтарин бит).
  • Усули илова кардани палитра

Усули LSB - усули маъмули стеганография. Он аз иваз кардани битҳои охирини муҳим дар контейнер (дар ҳолати мо, байтҳои палитраи глобалӣ) бо битҳои паёми пинҳон иборат аст.

Барнома ду битҳои охиринро дар байтҳои палитраи глобалӣ ҳамчун як қисми ин усул истифода мебарад. Ин маънои онро дорад, ки барои тасвири 24-бит, ки дар он ранги палитра се байт барои сурх, кабуд ва сабз аст, пас аз ворид кардани паём ба он, ҳар як ҷузъи ранг бо ҳадди аксар 3/255 градатсия тағир меёбад. Чунин таѓйирот, аввалан, ба чашми инсон ноаён ва ё пайхас кардан душвор хоњад буд, дуюм, дар дастгоњњои баромади иттилооти пастсифат дида намешавад.

Миқдори иттилоот бевосита аз андозаи палитраи тасвир вобаста аст. Азбаски андозаи максималии палитра 256 ранг аст ва агар ба ҷузъи ҳар як ранг ду битҳои хабарӣ навишта шаванд, он гоҳ дарозии максималии паём (бо палитраи максималӣ дар тасвир) 192 байт аст. Вақте ки паём дар тасвир ҷойгир карда мешавад, андозаи файл тағир намеёбад.

Усули васеъкунии палитра, ки танҳо барои сохтори GIF кор мекунад. Он дар тасвирҳои дорои палитраи хурд самараноктар хоҳад буд. Мохияти он дар он аст, ки вай андозаи палитраро зиёд мекунад ва ба ин васила барои навиштани байтхои зарурй ба чои байтхои ранг фазои иловаги медихад. Агар ба назар гирем, ки андозаи минималии палитра 2 ранг (6 байт) аст, он гоҳ андозаи максималии паёми воридшуда метавонад 256 × 3–6 = 762 байт бошад. Камбудӣ амнияти криптографии паст аст; паёми дарунсохтро метавон бо истифода аз ҳама гуна муҳаррири матн хонд, агар паём ба рамзгузории иловагӣ дучор нашуда бошад.

Қисми амал

Тарҳрезии барнома

Ҳама асбобҳои зарурӣ барои татбиқи алгоритмҳои рамзгузорӣ ва рамзкушоӣ ба баста дохил карда мешаванд com.tsarik.steganography. Ин баста интерфейсро дар бар мегирад Encryptor бо усулхо encrypt и decrypt, Синф Binary, ки қобилияти кор бо массивҳои бит ва инчунин синфҳои истисноиро таъмин мекунад UnableToEncryptException и UnableToDecryptException, ки бояд дар усулҳои интерфейс истифода шавад Encryptor дар сурати мувофикан хатогихои рамзгузорй ва рамзку-нй.

Бастаи асосии барнома com.tsarik.programs.gifed синфи барномаи иҷрошавандаро бо усули статикӣ дар бар мегирад main, ба шумо имкон медиҳад, ки барномаро иҷро кунед; синфе, ки параметрҳои барномаро нигоҳ медорад; ва бастаҳо бо синфҳои дигар.

Татбиқи худи алгоритмҳо дар баста пешниҳод карда мешаванд com.tsarik.programs.gifed.gif синфхо GIFEncryptorByLSBMethod и GIFEncryptorByPaletteExtensionMethod. Ҳардуи ин синфҳо интерфейсро амалӣ хоҳанд кард Encryptor.

Дар асоси сохтори формати GIF, шумо метавонед алгоритми умумиро барои ворид кардани паём ба палитраи тасвир эҷод кунед:

Стеганография дар GIF

Барои муайян кардани мавҷудияти хабар дар тасвир ба оғози паём як пайдарпайии муайяни битҳоро илова кардан лозим аст, ки декодер аввал онҳоро мехонад ва дурустии онро месанҷад. Агар он мувофиқат накунад, пас чунин ҳисобида мешавад, ки дар тасвир паёми пинҳонӣ вуҷуд надорад. Минбаъд шумо бояд дарозии паёмро муайян кунед. Баъд худи матни паём.

Диаграммаи синфии тамоми барнома:

Стеганография дар GIF

Татбики программа

Татбиқи тамоми барномаро метавон ба ду қисм ҷудо кард: татбиқи рамзгузории интерфейс ва усулҳои рамзкушоӣ Encryptor, дар синфхо GIFEncryptorByLSBMethod и GIFEncryptorByPaletteExtensionMethod, ва татбиқи интерфейси корбар.

Синфро баррасӣ кунед GIFEncryptorByLSBMethod.

Стеганография дар GIF

майдонҳои firstLSBit и secondLSBit дорои рақамҳои битҳои ҳар як байти тасвир, ки ба он паём бояд ворид карда шавад ва аз куҷо хонда шавад. Майдон checkSequence пайдарпаии битҳои чекро нигоҳ медорад, то эътирофи паёми воридшударо таъмин кунад. Усули статикӣ getEncryptingFileParameters параметрҳои файли муайяншуда ва хусусиятҳои паёми эҳтимолиро бармегардонад.

Алгоритми усул encrypt дараҷа GIFEncryptorByLSBMethod:

Стеганография дар GIF

Ва рамзи ӯ:

@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();
}

Алгоритм ва коди сарчашмаи метод decrypt дараҷа GIFEncryptorByLSBMethod:

Стеганография дар 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);
}

Татбиқи синф GIFEncryptorByPaletteExtensionMethod шабеҳ хоҳад буд, танҳо усули нигоҳдорӣ/хонидани иттилоот гуногун аст.

Дар синф MainFrame усулҳои бастабандӣ тавсиф шудаанд: encryptImage(Encryptor encryptor) и decryptImage(Encryptor encryptor), коркарди натиҷаҳои усулҳои интерфейс Encryptor ва муошират бо корбар, яъне кушодани муколамаи интихоби файл, нишон додани паёмҳои хато ва ғайра; инчунин усулҳои дигар: openImage(), ба корбар имкон медиҳад, ки тасвирро интихоб кунад, exit(), ки аз барнома мебарояд. Ин усулҳо аз номида мешаванд Actionҷузъҳои менюи мувофиқ. Ин синф ба таври илова усулҳои ёрирасонро амалӣ мекунад: createComponents() - эҷоди ҷузъҳои шакл; loadImageFile(File f) — бор кардани тасвир ба ҷузъи махсус аз файл. Татбиқи синф GIFEncryptorByPaletteExtensionMethod ба татбиқи синф монанд аст GIFEncryptorByLSBMethod, фарқияти асосӣ дар тарзи навиштан ва хондани байтҳои паём аз палитра аст.

Амалиёти барнома

Усули LBS

Фарз мекунем, ки чунин тасвир вуҷуд дорад:

Стеганография дар GIF

Дар ин тасвир палитра аз 256 ранг иборат аст (чунон ки Paint захира мекунад). Чор ранги аввал инҳоянд: сафед, сиёҳ, сурх, сабз. Рангҳои дигар сиёҳ мебошанд. Пайдарпаии битҳои палитраи глобалӣ чунин хоҳад буд:

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

Стеганография дар GIF

Пас аз ворид кардани паём, битҳои зерхатшуда бо битҳои паём иваз карда мешаванд. Тасвири ба даст овардашуда аз тасвири аслӣ қариб фарқ надорад.

Original
Тасвир бо паёми воридшуда

Стеганография дар GIF
Стеганография дар GIF

Усули васеъкунии палитра

Вақте ки шумо тасвири дорои паёмро бо истифода аз ин усул мекушоед, шумо расми зеринро хоҳед дид:

Стеганография дар GIF

Маълум аст, ки ин усул барои фаъолиятҳои пурраи ҷосусӣ кор намекунад ва метавонад рамзгузории иловагии паёмро талаб кунад.

Рамзгузорӣ / рамзкушоӣ дар тасвирҳои аниматсионӣ мисли тасвирҳои муқаррарии статикӣ кор мекунад, аммо аниматсия вайрон нашудааст.

Манбаъҳои истифодашуда:

Download:

Манбаъ: will.com

Илова Эзоҳ