GIF форматындагы стеганография

тааныштыруу

Салам.
Жакында мен университетте окуп жүргөндө «Маалыматтык коопсуздуктун программалык ыкмалары» дисциплинасы боюнча курстук иш бар болчу. Бул тапшырма бизден GIF файлдарына билдирүү камтыган программаны түзүүнү талап кылды. Мен муну Java тилинде жасоону чечтим.

Бул макалада мен кээ бир теориялык пункттарды, ошондой эле бул чакан программа түзүлгөн кантип сүрөттөп берем.

теоретикалык бөлүгү

GIF форматы

GIF (Graphics Interchange Format – сүрөттөрдү алмаштыруу форматы) – 256 түскө чейинки форматта сапатын жоготпостон кысылган маалыматтарды сактоого жөндөмдүү графикалык сүрөттөрдү сактоо форматы. Бул формат 1987-жылы (GIF87a) CompuServe тарабынан растр сүрөттөрүн тармактар ​​аркылуу өткөрүү үчүн иштелип чыккан. 1989-жылы формат өзгөртүлгөн (GIF89a), айкындуулукту жана анимацияны колдоо кошулган.

GIF файлдары блоктук түзүлүшкө ээ. Бул блоктордун ар дайым туруктуу узундугу бар (же бул кээ бир желектерге жараша болот), андыктан ар бир блоктун кайсы жерде жайгашканы жөнүндө ката кетирүү дээрлик мүмкүн эмес. GIF89a форматындагы эң жөнөкөй анимацияланбаган GIF сүрөтүнүн түзүлүшү:

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 (Least Significant Bit) ыкмасы
  • Палитрага кошуу ыкмасы

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 форматындагы стеганография

Билдирүү киргизилгенден кийин, асты сызылган биттер билдирүүнүн биттери менен алмаштырылат. Алынган сүрөт түп нускасынан дээрлик айырмаланбайт.

баштапкы
Камтылган билдирүү менен сүрөт

GIF форматындагы стеганография
GIF форматындагы стеганография

Палитраны кеңейтүү ыкмасы

Бул ыкманы колдонуу менен билдирүү камтыган сүрөттү ачканда, сиз төмөнкү сүрөттү көрөсүз:

GIF форматындагы стеганография

Бул ыкма толук кандуу шпиондук иш-аракеттер үчүн иштебей турганы түшүнүктүү жана билдирүүнүн кошумча шифрлөөсүн талап кылышы мүмкүн.

Анимацияланган сүрөттөрдө шифрлөө/дешифрлөө кадимки статикалык сүрөттөрдөгүдөй иштейт, бирок анимация бузулган эмес.

Колдонулган булактар:

жүктөп алуу:

Source: www.habr.com

Комментарий кошуу