Steganography ni GIF

Ifihan

Ẹ kí.
Kò pẹ́ púpọ̀ sẹ́yìn, nígbà tí mo ń kẹ́kọ̀ọ́ ní yunifásítì, iṣẹ́ ìdánilẹ́kọ̀ọ́ kan wà nínú ẹ̀kọ́ náà “Àwọn ọ̀nà ìsọfúnni tó ń dáàbò bo ìsọfúnni.” Iṣẹ iyansilẹ nilo wa lati ṣẹda eto kan ti o fi ifiranšẹ sinu awọn faili GIF. Mo pinnu lati ṣe ni Java.

Ninu nkan yii Emi yoo ṣe apejuwe diẹ ninu awọn aaye imọ-jinlẹ, bii bii eto kekere yii ṣe ṣẹda.

O tumq si apakan

GIF kika

GIF (Fọọmu Iyipada Aworan - ọna kika fun paṣipaarọ awọn aworan) jẹ ọna kika fun titoju awọn aworan ayaworan, ti o lagbara lati tọju data fisinuirindigbindigbin laisi pipadanu didara ni ọna kika to awọn awọ 256. Ọna kika yii jẹ idagbasoke ni ọdun 1987 (GIF87a) nipasẹ CompuServe fun gbigbe awọn aworan raster sori awọn nẹtiwọọki. Ni ọdun 1989, ọna kika ti yipada (GIF89a), atilẹyin fun akoyawo ati ere idaraya ti ṣafikun.

Awọn faili GIF ni eto idina kan. Awọn bulọọki wọnyi nigbagbogbo ni ipari ti o wa titi (tabi o da lori diẹ ninu awọn asia), nitorinaa o fẹrẹ ṣe ko ṣee ṣe lati ṣe aṣiṣe nipa ibiti bulọọki kọọkan wa. Eto ti aworan GIF ti kii ṣe ere idaraya ti o rọrun julọ ni ọna kika GIF89a:

Steganography ni GIF

Ninu gbogbo awọn bulọọki ti eto, ninu ọran yii a yoo nifẹ si bulọọki paleti agbaye ati awọn aye ti o ni iduro fun paleti naa:

  • CT - niwaju paleti agbaye. Ti a ba ṣeto asia yii, paleti agbaye gbọdọ bẹrẹ lẹsẹkẹsẹ lẹhin imudani iboju ọgbọn.
  • Size - iwọn paleti ati nọmba awọn awọ ninu aworan naa. Awọn iye fun paramita yii:

iwọn
Nọmba ti awọn awọ
Iwọn paleti, awọn baiti

7
256
768

6
128
384

5
64
192

4
32
96

3
16
48

2
8
24

1
4
12

0
2
6

Awọn ọna fifi ẹnọ kọ nkan

Awọn ọna wọnyi yoo ṣee lo lati fi awọn ifiranṣẹ pamọ sinu awọn faili aworan:

  • LSB (Kekere Significant Bit) ọna
  • Paleti afikun ọna

LSB ọna - ọna ti o wọpọ ti steganography. O ni rirọpo awọn die-die pataki ti o kẹhin ninu apoti (ninu ọran wa, awọn baiti paleti agbaye) pẹlu awọn ipin ti ifiranṣẹ ti o farapamọ.

Eto naa yoo lo awọn die-die meji to kẹhin ninu awọn baiti paleti agbaye gẹgẹbi apakan ti ọna yii. Eyi tumọ si pe fun aworan 24-bit, nibiti awọ paleti jẹ awọn baiti mẹta fun pupa, buluu, ati alawọ ewe, lẹhin fifi ifiranšẹ sinu rẹ, paati awọ kọọkan yoo yipada nipasẹ o pọju 3/255 gradations. Iru iyipada bẹ, ni akọkọ, yoo jẹ alaihan tabi nira lati ṣe akiyesi si oju eniyan, ati keji, kii yoo han lori awọn ẹrọ iṣelọpọ alaye didara kekere.

Iye alaye yoo dale taara lori iwọn paleti aworan naa. Niwọn igba ti iwọn ti o pọju ti paleti jẹ awọn awọ 256, ati pe ti awọn ifiranṣẹ ifiranṣẹ meji ba kọ sinu paati ti awọ kọọkan, lẹhinna ipari ifiranṣẹ ti o pọju (pẹlu paleti ti o pọju ninu aworan) jẹ 192 awọn baiti. Ni kete ti ifiranṣẹ ti wa ni ifibọ ninu aworan, iwọn faili ko yipada.

Paleti imugboroosi ọna, eyi ti o ṣiṣẹ fun ọna GIF nikan. Yoo munadoko julọ lori awọn aworan pẹlu paleti kekere kan. Ohun pataki rẹ ni pe o mu iwọn paleti naa pọ si, nitorinaa pese aaye afikun fun kikọ awọn baiti pataki ni aaye awọn baiti awọ. Ti a ba ro pe iwọn to kere julọ ti paleti jẹ awọn awọ 2 (6 baiti), lẹhinna iwọn ti o pọju ifiranṣẹ ti a fi sii le jẹ 256 × 3–6 = 762 awọn baiti. Alailanfani naa jẹ aabo cryptographic kekere; ifiranṣẹ ti a fi sinu le ṣee ka ni lilo eyikeyi olootu ọrọ ti ifiranṣẹ naa ko ba ti tẹriba si fifi ẹnọ kọ nkan.

Ilowo apakan

Apẹrẹ eto

Gbogbo awọn irinṣẹ pataki fun imuse fifi ẹnọ kọ nkan ati awọn algoridimu decryption yoo wa ninu package com.tsarik.steganography. Yi package pẹlu ni wiwo Encryptor pẹlu awọn ọna encrypt и decrypt, Kilasi Binary, eyi ti o pese agbara lati ṣiṣẹ pẹlu awọn ohun elo bit, bi daradara bi awọn kilasi iyasọtọ UnableToEncryptException и UnableToDecryptException, eyi ti o yẹ ki o lo ni awọn ọna wiwo Encryptor ni irú ti fifi koodu ati iyipada awọn aṣiṣe lẹsẹsẹ.

Akọkọ package eto com.tsarik.programs.gifed yoo pẹlu a runnable eto kilasi pẹlu kan aimi ọna main, gbigba ọ laaye lati ṣiṣe eto naa; kilasi ti o tọju awọn paramita eto; ati awọn idii pẹlu awọn kilasi miiran.

Awọn imuse ti awọn algoridimu funrararẹ yoo gbekalẹ ninu package com.tsarik.programs.gifed.gif awọn kilasi GIFEncryptorByLSBMethod и GIFEncryptorByPaletteExtensionMethod. Mejeji ti awọn wọnyi kilasi yoo se ni wiwo Encryptor.

Da lori eto ti ọna kika GIF, o le ṣẹda algorithm gbogbogbo fun iṣafihan ifiranṣẹ kan sinu paleti aworan:

Steganography ni GIF

Lati pinnu wiwa ti ifiranṣẹ kan ninu aworan, o jẹ dandan lati ṣafikun ọkọọkan awọn bit si ibẹrẹ ifiranṣẹ, eyiti oluyipada naa ka ni akọkọ ati ṣayẹwo fun deede. Ti ko ba baramu, lẹhinna o gba pe ko si ifiranṣẹ ti o farapamọ ninu aworan naa. Nigbamii o nilo lati pato ipari ti ifiranṣẹ naa. Lẹhinna ọrọ ti ifiranṣẹ naa funrararẹ.

Aworan kilasi ti gbogbo ohun elo:

Steganography ni GIF

Imuse ti awọn eto

Awọn imuse ti gbogbo eto le ti wa ni pin si meji irinše: imuse ti wiwo ìsekóòdù ati decryption awọn ọna Encryptor, ni awọn kilasi GIFEncryptorByLSBMethod и GIFEncryptorByPaletteExtensionMethod, ati imuse ti wiwo olumulo.

Wo kilasi naa GIFEncryptorByLSBMethod.

Steganography ni GIF

Awọn aaye firstLSBit и secondLSBit ni awọn nọmba ti awọn die-die ti kọọkan baiti ti aworan ninu eyi ti awọn ifiranṣẹ yẹ ki o wa ni titẹ ati lati ibi ti awọn ifiranṣẹ yẹ ki o wa ka. Aaye checkSequence tọjú a ayẹwo bit ọkọọkan lati rii daju ti idanimọ ti awọn ifibọ ifiranṣẹ. ọna aimi getEncryptingFileParameters da pada awọn paramita ti awọn pàtó kan faili ati awọn abuda kan ti o pọju ifiranṣẹ.

Ọna algorithm encrypt kilasi GIFEncryptorByLSBMethod:

Steganography ni GIF

Ati koodu rẹ:

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

Algoridimu ati koodu orisun ti ọna decrypt kilasi GIFEncryptorByLSBMethod:

Steganography ni 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);
}

Imuse ti awọn kilasi GIFEncryptorByPaletteExtensionMethod yoo jẹ iru, nikan ọna ti fifipamọ / kika alaye ti o yatọ si.

Ninu kilasi MainFrame Awọn ọna wiwu ti wa ni apejuwe: encryptImage(Encryptor encryptor) и decryptImage(Encryptor encryptor), processing awọn esi ti awọn ọna wiwo Encryptor ati ibaraenisepo pẹlu olumulo, ie ṣiṣii ọrọ sisọ yiyan faili kan, fifi awọn ifiranṣẹ aṣiṣe han, ati bẹbẹ lọ; ati awọn ọna miiran: openImage(), gbigba olumulo laaye lati yan aworan kan, exit(), eyi ti o jade ohun elo. Awọn ọna wọnyi ni a npe ni lati ActionAwọn ohun akojọ aṣayan ti o baamu. Kilasi yii tun ṣe awọn ọna iranlọwọ: createComponents() - ṣiṣẹda awọn ẹya ara fọọmu, loadImageFile(File f) - ikojọpọ aworan sinu paati pataki lati faili kan. Imuse ti awọn kilasi GIFEncryptorByPaletteExtensionMethod iru si imuse kilasi GIFEncryptorByLSBMethod, Iyatọ akọkọ jẹ ni ọna ti awọn baiti ifiranṣẹ ti kọ ati ka lati paleti.

Isẹ eto

LBS ọna

Jẹ ki a sọ pe aworan kan wa bi eleyi:

Steganography ni GIF

Ni aworan yii, paleti naa ni awọn awọ 256 (gẹgẹbi Awọn fifipamọ Kun). Awọn awọ mẹrin akọkọ jẹ: funfun, dudu, pupa, alawọ ewe. Awọn awọ miiran jẹ dudu. Ọkọọkan paleti agbaye yoo jẹ bi atẹle:

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

Steganography ni GIF

Ni kete ti ifiranṣẹ ba ti wa ni ifibọ, awọn abẹlẹ abẹlẹ yoo rọpo pẹlu awọn die-die lati ifiranṣẹ naa. Abajade aworan jẹ fere ko yatọ si atilẹba.

Atilẹba
Aworan pẹlu ifibọ ifiranṣẹ

Steganography ni GIF
Steganography ni GIF

Paleti imugboroosi ọna

Nigbati o ba ṣii aworan ti o ni ifiranṣẹ kan ni lilo ọna yii, iwọ yoo wo aworan atẹle:

Steganography ni GIF

O han gbangba pe ọna yii kii yoo ṣiṣẹ fun awọn iṣẹ amí ni kikun, ati pe o le nilo fifi ẹnọ kọ nkan ti ifiranṣẹ naa.

Ìsekóòdù/ìsọdipúpọ̀ nínú àwọn àwòrán eré ìdárayá ń ṣiṣẹ́ gẹ́gẹ́ bí àwọn àwòrán àìmimọ́ déédéé, ṣùgbọ́n eré ìnàjú náà kò fọ́.

Awọn orisun ti a lo:

Gba lati ayelujara:

orisun: www.habr.com

Fi ọrọìwòye kun