Steganographia in GIF

introduction

Ρ€ΠΈΠ²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽ.
Haud ita pridem, cum apud universitatem studerem, cursus in disciplina "Software methodi informationis securitatis" erat. Assignatio postulavit ut programma crearet quod nuntium in GIF imagini implicat. Id facere constitui in Java.

In hoc articulo nonnulla puncta theorica describam, itemque quomodo haec parva programma facta sit.

Pars theorica

GIF format

GIF (Graphica forma permutationis - forma ad commutandas imagines) forma est ad imagines graphicas reponendas, capax notitiarum compressarum recondens sine detrimento qualitatis in forma usque ad 256 colores. Forma haec anno 1987 (GIF87a) evoluta est a CompuServe ad imagines rasterarum transmittendis in retiacula. Anno 1989, forma mutata est (GIF89a), subsidium perspicuitatis et animationis addita est.

GIF files structuram obstructionum habent. Semper hae caudices certam longitudinem habent (vel ab aliqua vexilla pendent), ut fere impossibile sit errare ubi quisque clausus situs est. Structura imaginis simplicissimae non animatae GIF in forma GIF89a:

Steganographia in GIF

Inter omnes structurarum cuneos, hoc in casu erimus curae in palette globali ac parametris palette responsales:

  • CT - praesentia palette globalis. Si hoc vexillum positum est, palette globalis statim post ansam logicae ductili incipere debet.
  • Size β€” palette magnitudo et numerus colorum in pictura. Valores huius moduli:

Size
Numerus colorum
Magnitudo palette, 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

Encryption modi

Modi sequentes epistulas encryptas in imaginum imaginum notas adhibebunt;

  • LSB (minime significat Bit) modum
  • Palette praeter modum

LSB methodo β€” Steganographiae methodus communis. Constat reponere ultimas notabiles frenos in vase (in nostro casu bytes globalis) cum lamellis nuntii occulti.

Propositum utetur duabus ultimis bits in palette globali bytes ut partem huius methodi. Hoc significat imaginem pro 24 frenum, ubi color palette tres bytes pro rubro, caeruleo et viridi est, postquam nuntium in illam involvit, unumquemque componentium color per maximum gradum graduum 3/255 mutabit. Talis mutatio, primo, erit invisibilis vel difficilis ad noticiam humano oculo, secundo, non erit visi- bilis qualitas notitia output machinas.

Moles informationum directe dependet a magnitudine imaginis palette. Cum magnitudo palette maxima 256 colores est, et si duae epistulae minutae scriptae sunt in componente cuiusque coloris, maximus nuntius longitudo (cum maximo palette in imagine) 192 bytes est. Cum nuntius in imagine infixus est, magnitudo fasciculi non mutat.

Expansion modum Palettequi tantum ad GIF structuram operatur. Efficacissima erit in imaginibus cum parvo palette. Essentia eius est ut palette magnitudinem augeat, eo addito spatium ad scribendum necessaria bytes loco coloris bytes. Si magnitudinem palette consideramus minimam esse 2 colores (6 bytes), tunc maxima magnitudo nuntiorum infixa potest esse 256 Γ— 3-6 = 762 bytes. Incommodum securitatis cryptographicae humilis est, nuntius integer legi potest utens aliquo textu editore si nuntius additae encryptioni subiecta non est.

Insignia sunt practica parte,

Programma design

Omnia instrumenta necessaria ad exsequendam encryptionem et decryptionem algorithmorum in fasciculo includuntur com.tsarik.steganography. Hoc sarcina includit interface Encryptor cum modi encrypt ΠΈ decrypt, Classis Binary, quae facultatem praebet ad operandum cum aliquas personas, ac etiam exceptiones classes UnableToEncryptException ΠΈ UnableToDecryptException, quae adhibeantur modi instrumenti instrumenti Encryptor in casu de erroribus delatam et decoding respective.

Principalis progressio sarcina com.tsarik.programs.gifed et includere runnable genus progressio cum stabili methodo mainpermittens vobis propositum currere; genus penu programmatis parametri; et fasciculi cum aliis generibus.

Ipsa algorithmorum exsecutio in sarcina exhibebitur com.tsarik.programs.gifed.gif classes GIFEncryptorByLSBMethod ΠΈ GIFEncryptorByPaletteExtensionMethod. Utrumque genus horum instrumentorum efficiet Encryptor.

Fundata ex structura GIF format, algorithmum generale creare potes ut nuntium in palette imaginem inducas:

Steganographia in GIF

Ut praesentiam nuntii in imagine determinet, necesse est ut quamdam iunci seriem addat ad initium nuntium, quem decoder prius legit et ad rectitudinem sistit. Si non congruit, tunc consideratur nullum esse in imagine nuntium absconditum. Proximam nuntiationis longitudinem denotare debes. Tunc textus ipsius relatum est ipsum.

Classis totius schematis applicatio:

Steganographia in GIF

Exsequendam programma

Exsecutio totius progressionis in duas partes dividi potest: exsecutio methodorum interfaciei encryption et decryption EncryptorIn classes GIFEncryptorByLSBMethod ΠΈ GIFEncryptorByPaletteExtensionMethodac exsequenda interface.

Considerans genus GIFEncryptorByLSBMethod.

Steganographia in GIF

agri firstLSBit ΠΈ secondLSBit contineant numeros frustularum cuiusque byte imaginis in quas nuntius ineatur et unde nuntius legendus est. Agro checkSequence perscriptio partem addit seriem ut recognitionem embedded nuntium. Statica methodo getEncryptingFileParameters parametros refert tabellae definitae et characteres nuntiorum potentialium.

Methodus algorithmus encrypt class GIFEncryptorByLSBMethod:

Steganographia in GIF

et codicem suum;

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

Algorithmus et fons Codicis methodi decrypt class GIFEncryptorByLSBMethod:

Steganographia in 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);
}

Classis exsequendam GIFEncryptorByPaletteExtensionMethod similis erit, modo ratio salutaris/legii notitias differet.

In genere MainFrame fasciae modos descriptae sunt; encryptImage(Encryptor encryptor) ΠΈ decryptImage(Encryptor encryptor), Eventus modi interface dispensando Encryptor and interacting with the user, i.e., opening a file selection alternis, errorem nuntiis, etc. tum alii modi; openImage()permittens utentis imaginem deligere; exit()qui ex applicatione. Hae modi dicuntur e Actions menu respondentis items. Hoc genus praeterea instrumentorum auxiliariorum instrumentorum est: createComponents() β€” forma- tium creatio; loadImageFile(File f) β€” Imaginem in speciali componentia ex lima onerare. Classis exsequendam GIFEncryptorByPaletteExtensionMethod similis genus implementation GIFEncryptorByLSBMethodsumma differentia est in modo nuntiorum bytes scribuntur et legunt ex palette.

Program operandi

LBS modum

Dicamus imaginem esse huius modi;

Steganographia in GIF

In hac imagine, palette ex 256 coloribus (sicut Poena servat). Quattuor primi colores sunt: ​​albus, niger, ruber, viridis. Alii colores nigri sunt. Sequentia palettae globalis paulum sic erit:

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

Steganographia in GIF

Postquam nuntius immersus est, frena fucosa cum frenis e nuntio restituetur. Imago inde ab originali paene non differt.

original
Imago cum embedded nuntium

Steganographia in GIF
Steganographia in GIF

Expansion modum Palette

Cum imaginem aperis continens nuntium hac methodo utens, sequentem imaginem videbis:

Steganographia in GIF

Patet hanc methodum non operari ad actiones plenae explorationis incertae et encryptionem nuntiationis requirere.

Encryption/decryption in imaginibus animatis tantum operatur sicut in imaginibus staticis regularibus, sed animatio non frangitur.

Fontes usus est:

download:

Source: www.habr.com