سټیګنګرافي په GIF کې

پېژندنه

سلامونه.
ډیر وخت دمخه، کله چې ما په پوهنتون کې زده کړه کوله، د "معلوماتو د خوندیتوب سافټویر میتودونه" په ډسپلین کې کورس ورک و. دنده موږ ته اړتیا درلوده چې یو برنامه جوړه کړو چې د GIF فایلونو کې پیغام ځای په ځای کړي. ما پریکړه وکړه چې دا په جاوا کې وکړم.

پدې مقاله کې زه به ځینې نظریاتي ټکي بیان کړم، او همدارنګه دا کوچنی پروګرام څنګه جوړ شو.

نظري برخه

د GIF بڼه

GIF (د ګرافیک تبادلې فارمیټ - د عکسونو تبادلې فارمیټ) د ګرافیک عکسونو ذخیره کولو فارمیټ دی چې د 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 (لږترلږه د پام وړ بټ) میتود
  • د پیلټ اضافه کولو طریقه

د LSB طریقه - د سټیګنګرافي یو عام میتود. دا په کانټینر کې د وروستي پام وړ بټونو (زموږ په قضیه کې، د نړیوال پیلټ بایټس) د پټ پیغام بټونو سره ځای په ځای کول شامل دي.

برنامه به د دې میتود یوې برخې په توګه د نړیوال پیلټ بایټس کې وروستي دوه بټونه وکاروي. دا پدې مانا ده چې د 24-bit عکس لپاره، چیرې چې د رنګ پیلټ د سور، نیلي او شین لپاره درې بایټونه دي، وروسته له دې چې په دې کې یو پیغام سرایت وکړي، د هر رنګ اجزا به د اعظمي 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 رنګونه لري (لکه څنګه چې پینټ خوندي کوي). لومړی څلور رنګونه دي: سپین، تور، سور، شنه. نور رنګونه تور دي. د نړیوال پیلټ بټ ترتیب به په لاندې ډول وي:

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

سټیګنګرافي په GIF کې

یوځل چې پیغام سرایت شي ، لاندې لیک شوي بټونه به د پیغام له بټونو سره بدل شي. پایله لرونکی عکس تقریبا د اصلي څخه توپیر نلري.

اصلي
انځور د ایمبیډ شوي پیغام سره

سټیګنګرافي په GIF کې
سټیګنګرافي په GIF کې

د پیلټ پراخولو طریقه

کله چې تاسو د دې طریقې په کارولو سره یو پیغام پرانیزئ، تاسو به لاندې انځور وګورئ:

سټیګنګرافي په GIF کې

دا روښانه ده چې دا طریقه به د بشپړ جاسوسي فعالیتونو لپاره کار ونکړي، او ممکن د پیغام اضافي کوډ کولو ته اړتیا ولري.

په متحرک عکسونو کې کوډ کول / ډیکرپشن د منظم جامد عکسونو په څیر کار کوي ، مګر حرکت نه مات شوی.

کارول شوي سرچینې:

کښته کول:

سرچینه: www.habr.com

Add a comment