Steganography sa GIF

Pagpapakilala

Pagbati.
Hindi pa katagal, noong nag-aaral ako sa unibersidad, nagkaroon ng coursework sa disiplina na "Software method of information security." Ang pagtatalaga ay nangangailangan sa amin na lumikha ng isang programa na nag-e-embed ng isang mensahe sa mga GIF file. Nagpasya akong gawin ito sa Java.

Sa artikulong ito ay ilalarawan ko ang ilang mga teoretikal na punto, pati na rin kung paano nilikha ang maliit na programang ito.

Teoretikal na bahagi

GIF format

Ang GIF (Graphics Interchange Format - isang format para sa pagpapalitan ng mga larawan) ay isang format para sa pag-imbak ng mga graphic na larawan, na may kakayahang mag-imbak ng naka-compress na data nang hindi nawawala ang kalidad sa isang format na hanggang 256 na kulay. Ang format na ito ay binuo noong 1987 (GIF87a) ng CompuServe para sa pagpapadala ng mga raster na imahe sa mga network. Noong 1989, binago ang format (GIF89a), idinagdag ang suporta para sa transparency at animation.

Ang mga GIF file ay may istraktura ng bloke. Ang mga bloke na ito ay palaging may nakapirming haba (o depende ito sa ilang mga flag), kaya halos imposibleng magkamali tungkol sa kung saan matatagpuan ang bawat bloke. Ang istruktura ng pinakasimpleng hindi animated na GIF na imahe sa GIF89a na format:

Steganography sa GIF

Sa lahat ng mga bloke ng istraktura, sa kasong ito ay magiging interesado kami sa pandaigdigang palette block at ang mga parameter na responsable para sa palette:

  • CT β€” pagkakaroon ng isang pandaigdigang palette. Kung nakatakda ang flag na ito, dapat magsimula kaagad ang global palette pagkatapos ng logical screen handle.
  • Size β€” laki ng palette at bilang ng mga kulay sa larawan. Mga halaga para sa parameter na ito:

laki
Bilang ng mga kulay
Laki ng 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

Mga paraan ng pag-encrypt

Ang mga sumusunod na pamamaraan ay gagamitin upang i-encrypt ang mga mensahe sa mga file ng imahe:

  • Paraang LSB (Least Significant Bit).
  • Paraan ng pagdaragdag ng palette

Paraan ng LSB - isang karaniwang paraan ng steganography. Binubuo ito ng pagpapalit ng mga huling makabuluhang bit sa lalagyan (sa aming kaso, ang global palette byte) ng mga bit ng nakatagong mensahe.

Gagamitin ng programa ang huling dalawang bits sa global palette bytes bilang bahagi ng pamamaraang ito. Nangangahulugan ito na para sa isang 24-bit na imahe, kung saan ang color palette ay tatlong byte para sa pula, asul, at berde, pagkatapos mag-embed ng isang mensahe dito, ang bawat bahagi ng kulay ay magbabago ng maximum na 3/255 gradations. Ang ganitong pagbabago, una, ay magiging invisible o mahirap mapansin ng mata ng tao, at pangalawa, hindi ito makikita sa mababang kalidad na mga device na output ng impormasyon.

Ang dami ng impormasyon ay direktang magdedepende sa laki ng palette ng larawan. Dahil ang maximum na laki ng palette ay 256 na kulay, at kung ang dalawang bits ng mensahe ay nakasulat sa bahagi ng bawat kulay, kung gayon ang maximum na haba ng mensahe (na may pinakamataas na palette sa larawan) ay 192 bytes. Kapag ang mensahe ay naka-embed sa imahe, ang laki ng file ay hindi nagbabago.

Paraan ng pagpapalawak ng palette, na gumagana lamang para sa istraktura ng GIF. Ito ay magiging pinaka-epektibo sa mga larawang may maliit na palette. Ang kakanyahan nito ay pinapataas nito ang laki ng palette, sa gayon ay nagbibigay ng karagdagang espasyo para sa pagsusulat ng mga kinakailangang byte sa halip na mga byte ng kulay. Kung isasaalang-alang namin na ang pinakamababang laki ng palette ay 2 kulay (6 bytes), kung gayon ang maximum na laki ng naka-embed na mensahe ay maaaring 256 Γ— 3–6 = 762 bytes. Ang kawalan ay mababa ang cryptographic na seguridad; ang naka-embed na mensahe ay maaaring basahin gamit ang anumang text editor kung ang mensahe ay hindi sumailalim sa karagdagang pag-encrypt.

Praktikal na bahagi

Disenyo ng programa

Ang lahat ng kinakailangang tool para sa pagpapatupad ng encryption at decryption algorithm ay isasama sa package com.tsarik.steganography. Kasama sa package na ito ang interface Encryptor may mga pamamaraan encrypt ΠΈ decrypt, Klase Binary, na nagbibigay ng kakayahang magtrabaho kasama ang mga bit array, pati na rin ang mga exception class UnableToEncryptException ΠΈ UnableToDecryptException, na dapat gamitin sa mga pamamaraan ng interface Encryptor sa kaso ng mga error sa pag-encode at pag-decode ayon sa pagkakabanggit.

Pangunahing pakete ng programa com.tsarik.programs.gifed ay magsasama ng isang runnable na klase ng programa na may static na pamamaraan main, na nagpapahintulot sa iyo na patakbuhin ang programa; isang klase na nag-iimbak ng mga parameter ng programa; at mga pakete sa iba pang mga klase.

Ang pagpapatupad ng mga algorithm mismo ay ipapakita sa package com.tsarik.programs.gifed.gif mga klase GIFEncryptorByLSBMethod ΠΈ GIFEncryptorByPaletteExtensionMethod. Ang parehong mga klase ay magpapatupad ng interface Encryptor.

Batay sa istraktura ng GIF format, maaari kang lumikha ng isang pangkalahatang algorithm para sa pagpapasok ng isang mensahe sa palette ng imahe:

Steganography sa GIF

Upang matukoy ang pagkakaroon ng isang mensahe sa isang imahe, kinakailangan upang magdagdag ng isang tiyak na pagkakasunud-sunod ng mga bit sa simula ng mensahe, na unang binabasa ng decoder at sinusuri kung tama. Kung hindi ito tumutugma, pagkatapos ay itinuturing na walang nakatagong mensahe sa larawan. Susunod na kailangan mong tukuyin ang haba ng mensahe. Tapos yung text ng message mismo.

Class diagram ng buong application:

Steganography sa GIF

Pagpapatupad ng programa

Ang pagpapatupad ng buong programa ay maaaring nahahati sa dalawang bahagi: pagpapatupad ng interface encryption at mga pamamaraan ng decryption Encryptor, sa mga klase GIFEncryptorByLSBMethod ΠΈ GIFEncryptorByPaletteExtensionMethod, at ang pagpapatupad ng user interface.

Isaalang-alang ang klase GIFEncryptorByLSBMethod.

Steganography sa GIF

Field firstLSBit ΠΈ secondLSBit naglalaman ng mga bilang ng mga bit ng bawat byte ng imahe kung saan dapat ilagay ang mensahe at kung saan dapat basahin ang mensahe. Patlang checkSequence nag-iimbak ng check bit sequence upang matiyak ang pagkilala sa naka-embed na mensahe. Static na pamamaraan getEncryptingFileParameters ibinabalik ang mga parameter ng tinukoy na file at ang mga katangian ng potensyal na mensahe.

Algoritmo ng pamamaraan encrypt klase GIFEncryptorByLSBMethod:

Steganography sa GIF

At ang kanyang code:

@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 at source code ng pamamaraan decrypt klase GIFEncryptorByLSBMethod:

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

Pagpapatupad ng klase GIFEncryptorByPaletteExtensionMethod Magiging magkatulad, iba lang ang paraan ng pag-save/pagbasa ng impormasyon.

Sa klase MainFrame Ang mga pamamaraan ng wrapper ay inilarawan: encryptImage(Encryptor encryptor) ΠΈ decryptImage(Encryptor encryptor), pagproseso ng mga resulta ng mga pamamaraan ng interface Encryptor at pakikipag-ugnayan sa user, ibig sabihin, pagbubukas ng dialog ng pagpili ng file, pagpapakita ng mga mensahe ng error, atbp.; pati na rin ang iba pang mga pamamaraan: openImage(), na nagpapahintulot sa user na pumili ng isang larawan, exit(), na lumabas sa application. Ang mga pamamaraang ito ay tinatawag mula sa Actionang kaukulang mga item sa menu. Ang klase na ito ay nagpapatupad din ng mga pantulong na pamamaraan: createComponents() - paglikha ng mga bahagi ng form, loadImageFile(File f) β€” naglo-load ng isang imahe sa isang espesyal na bahagi mula sa isang file. Pagpapatupad ng klase GIFEncryptorByPaletteExtensionMethod katulad ng pagpapatupad ng klase GIFEncryptorByLSBMethod, ang pangunahing pagkakaiba ay sa paraan ng pagsusulat at pagbabasa ng mga byte ng mensahe mula sa palette.

Pagpapatakbo ng programa

Paraan ng LBS

Sabihin nating mayroong isang imahe tulad nito:

Steganography sa GIF

Sa larawang ito, ang palette ay binubuo ng 256 na kulay (habang nagse-save ang Paint). Ang unang apat na kulay ay: puti, itim, pula, berde. Itim ang ibang kulay. Ang global palette bit sequence ay ang mga sumusunod:

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

Steganography sa GIF

Kapag na-embed na ang mensahe, ang mga nakasalungguhit na bit ay papalitan ng mga bit mula sa mensahe. Ang resultang imahe ay halos hindi naiiba sa orihinal.

Orihinal
Larawang may naka-embed na mensahe

Steganography sa GIF
Steganography sa GIF

Paraan ng pagpapalawak ng palette

Kapag binuksan mo ang isang imahe na naglalaman ng isang mensahe gamit ang paraang ito, makikita mo ang sumusunod na larawan:

Steganography sa GIF

Malinaw na ang pamamaraang ito ay hindi gagana para sa ganap na mga aktibidad ng espiya, at maaaring mangailangan ng karagdagang pag-encrypt ng mensahe.

Ang pag-encrypt/pag-decryption sa mga animated na larawan ay gumagana tulad ng sa mga regular na static na larawan, ngunit ang animation ay hindi nasira.

Ginamit ang mga mapagkukunan:

I-download:

Pinagmulan: www.habr.com

Magdagdag ng komento