Steganography di GIF de

Pîrozbahiyê

Silav.
Demek berê, dema ku min li zanîngehê dixwend, di dîsîplîna "Rêbazên nermalava ewlehiya agahdariyê de" qursek hebû. Wezîfe ji me re lazim bû ku em bernameyek ku peyamek di pelên GIF-ê de vedihewîne biafirînin. Min biryar da ku ez li Java-ê bikim.

Di vê gotarê de ez ê çend xalên teorîk, û her weha çawa ev bernama piçûk hatî çêkirin vebêjim.

Beşa teorîk

Forma GIF

GIF (Formata Danûstandina Grafikan - formatek ji bo guheztina wêneyan) formatek e ji bo hilanîna wêneyên grafîkî, ku dikare daneyên pêçandî bêyî windakirina kalîteyê di formatek heya 256 rengan de hilîne. Ev format di sala 1987-an de (GIF87a) ji hêla CompuServe ve ji bo veguheztina wêneyên rasterê li ser torê hate pêşve xistin. Di sala 1989 de, format hate guherandin (GIF89a), piştgirî ji bo zelalbûn û anîmasyonê hate zêdekirin.

Pelên GIF xwedan avahiyek blokê ye. Van blokan her gav xwedan dirêjiyek sabît in (an jî ew bi hin alayan ve girêdayî ye), ji ber vê yekê hema ne gengaz e ku meriv xeletiyek li ku derê ye her blok bike. Struktura wêneya GIF ya ne-anîmasyon a herî hêsan a di formata GIF89a de:

Steganography di GIF de

Ji hemî blokên strukturê, di vê rewşê de em ê bala xwe bidin bloka paleta gerdûnî û pîvanên berpirsiyar ên paletê:

  • CT - hebûna paletek gerdûnî. Ger ev ala were danîn, divê paleta gerdûnî tavilê piştî destana ekrana mentiqî dest pê bike.
  • Size - Mezinahiya paletê û hejmara rengan di wêneyê de. Nirxên ji bo vê parametreyê:

Mezinayî
Hejmara rengan
Mezinahiya paletê, bytes

7
256
768

6
128
384

5
64
192

4
32
96

3
16
48

2
8
24

1
4
12

0
2
6

Rêbazên şîfrekirinê

Rêbazên jêrîn dê ji bo şîfrekirina peyamên di pelên wêneyê de werin bikar anîn:

  • Rêbaza LSB (Bîka Kêm Girîng).
  • Rêbaza zêdekirina paletê

rêbaza LSB - rêbazek hevpar a steganografiyê. Ew ji guheztina bitsên girîng ên paşîn ên di konteynerê de (di rewşa me de, baytên paleta gerdûnî) bi bitên peyama veşartî pêk tê.

Bername dê du bitên paşîn ên di baytên paleta gerdûnî de wekî beşek ji vê rêbazê bikar bîne. Ev tê vê wateyê ku ji bo wêneyek 24-bit, ku paleta rengan ji bo sor, şîn û kesk sê byte ye, piştî ku mesajek tê de bi cih kirin, her pêkhateyek reng dê herî zêde 3/255 dereceyan biguheze. Guhertinek wusa, ya yekem, dê ji çavê mirov re neyê dîtin an jî dijwar be, û ya duyemîn jî, ew ê li ser cîhazên hilberana agahdariya kêm-kalîteyê neyê dîtin.

Hejmara agahdarî dê rasterast bi mezinahiya paleta wêneyê ve girêdayî be. Ji ber ku mezinahiya herî zêde ya paletê 256 reng e, û ger du bit peyaman di pêkhateya her reng de were nivîsandin, wê hingê dirêjahiya peyamê ya herî zêde (bi paleta herî zêde ya di wêneyê de) 192 byte ye. Dema ku peyam di nav wêneyê de tête kirin, mezinahiya pelê nayê guhertin.

Rêbaza berfirehkirina paletê, ku tenê ji bo avahiya GIF-ê dixebite. Ew ê li ser wêneyên bi paletek piçûk herî bandorker be. Esasê wê ev e ku ew mezinahiya paletê zêde dike, bi vî rengî cîhek zêde peyda dike ji bo nivîsandina baytên pêwîst li şûna baytên rengan. Ger em bihesibînin ku mezinahiya herî hindik a paletê 2 reng e (6 byte), wê hingê mezinahiya herî zêde ya peyama pêvekirî dikare 256 × 3–6 = 762 byte be. Kêmasî ewlehiya krîptografî ya hindik e; heke peyam ji şîfrekirina zêde nehatibe kirin, peyama pêvekirî dikare bi karanîna her edîtorek nivîsê were xwendin.

Beşek pratîkî

Sêwirana bernameyê

Hemî amûrên pêwîst ên ji bo pêkanîna algorîtmayên şîfrekirin û şîfrekirinê dê di pakêtê de cih bigirin com.tsarik.steganography. Di vê pakêtê de navberê heye Encryptor bi rêbazên encrypt и decrypt, Class Binary, ku şiyana xebitandina bi rêzikên bit, û hem jî çînên îstîsnayê peyda dike UnableToEncryptException и UnableToDecryptException, ku divê di rêbazên navberê de were bikar anîn Encryptor bi rêzê ve çewtiyên şîfrekirinê û deşîfrekirinê.

Pakêta bernameya sereke com.tsarik.programs.gifed dê bi rêbazek statîk re çînek bernameyek bi rêve bibe main, dihêle hûn bernameyê bimeşînin; çînek ku pîvanên bernameyê diparêze; û pakêtên bi çînên din.

Pêkanîna algorîtmayan bixwe dê di pakêtê de were pêşkêş kirin com.tsarik.programs.gifed.gif çînên GIFEncryptorByLSBMethod и GIFEncryptorByPaletteExtensionMethod. Van her du çîn dê pêvekê bicîh bikin Encryptor.

Li ser bingeha avahiya formata GIF-ê, hûn dikarin algorîtmayek gelemperî ji bo danasîna peyamek di paleta wêneyê de biafirînin:

Steganography di GIF de

Ji bo destnîşankirina hebûna peyamek di wêneyekê de, pêdivî ye ku meriv rêzek bit li destpêka peyamê zêde bike, ku dekoder pêşî dixwîne û rastbûna wê kontrol dike. Ger ew li hev nebe, wê hingê tê hesibandin ku di wêneyê de peyamek veşartî tune. Piştre hûn hewce ne ku dirêjahiya peyamê diyar bikin. Piştre nivîsa peyamê bixwe.

Diagrama polê ya tevahiya serîlêdanê:

Steganography di GIF de

Pêkanîna bernameyê

Pêkanîna tevaya bernameyê dikare li du beşan were dabeş kirin: pêkanîna şîfrekirina navbeynkar û rêbazên deşîfrekirinê Encryptor, di dersan de GIFEncryptorByLSBMethod и GIFEncryptorByPaletteExtensionMethod, û pêkanîna navrûya bikarhêner.

Dersê bifikirin GIFEncryptorByLSBMethod.

Steganography di GIF de

zeviyên firstLSBit и secondLSBit jimareyên bitsên her bytê wêneyê ku divê peyam tê de were nivîsandin û ji ku derê peyam were xwendin hene. Erd checkSequence Rêzek bit a kontrolê hildide da ku naskirina peyama bicîbûyî piştrast bike. Rêbaza statîk getEncryptingFileParameters Parametreyên pelê diyarkirî û taybetmendiyên peyama potansiyel vedigerîne.

Algorîtmaya rêbazê encrypt çîn GIFEncryptorByLSBMethod:

Steganography di GIF de

Û koda wî:

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

Algorithm û koda çavkaniyê ya rêbazê decrypt çîn GIFEncryptorByLSBMethod:

Steganography di GIF de

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

Pêkanîna dersê GIFEncryptorByPaletteExtensionMethod dê dişibin hev, tenê awayê tomarkirin/xwendina agahiyan cuda ye.

Di polê de MainFrame Rêbazên wrapper têne diyar kirin: encryptImage(Encryptor encryptor) и decryptImage(Encryptor encryptor), Pêvajoya encamên rêbazên navberê Encryptor û bi bikarhêner re danûstendin, ango vekirina diyalogek hilbijartina pelê, nîşandana peyamên xeletiyê, hwd.; û her weha rêbazên din: openImage(), dihêle ku bikarhêner wêneyek hilbijêrin, exit(), ku ji serîlêdanê derdikeve. Ji van rêbazan têne gotin Actionhêmanên menuya têkildar. Ev çîn di heman demê de rêbazên alîkar bicîh tîne: createComponents() - afirandina pêkhateyên formê, loadImageFile(File f) - barkirina wêneyek ji pelê di hêmanek taybetî de. Pêkanîna dersê GIFEncryptorByPaletteExtensionMethod dişibin pêkanîna polê GIFEncryptorByLSBMethod, Cûdahiya sereke di awayê nivîsandin û xwendina baytên peyamê de ji paletê ye.

Operasyona bernameyê

Rêbaza LBS

Em bêjin wêneyek bi vî rengî heye:

Steganography di GIF de

Di vê wêneyê de, palet ji 256 rengan pêk tê (wekî ku Paint xilas dike). Çar rengên pêşîn ev in: spî, reş, sor, kesk. Rengên din reş in. Rêzeya bit ya paleta gerdûnî dê wiha be:

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

Steganography di GIF de

Dema ku peyam hat bicîkirin, bitsên binxêzkirî dê bi bitên ji peyamê re werin guhertin. Wêneya encam hema hema ji ya orîjînal cûda nabe.

Eslî
Wêne bi peyama bicîbûyî

Steganography di GIF de
Steganography di GIF de

Rêbaza berfirehkirina paletê

Dema ku hûn bi vê rêbazê wêneyek ku peyamek tê de vedikin, hûn ê wêneya jêrîn bibînin:

Steganography di GIF de

Eşkere ye ku ev rêbaz dê ji bo çalakiyên sîxuriyê yên bêkêmasî nexebite, û dibe ku şîfrekirina zêde ya peyamê hewce bike.

Şîfrekirin/deşîfrekirin di wêneyên anîmasyonî de mîna wêneyên statîk ên birêkûpêk dixebite, lê anîmasyon nayê şikandin.

Çavkaniyên bikaranîn:

Daxistin:

Source: www.habr.com

Add a comment