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 (کم سے کم اہم بٹ) طریقہ
  • پیلیٹ شامل کرنے کا طریقہ

ایل ایس بی کا طریقہ - سٹیگنوگرافی کا ایک عام طریقہ۔ یہ کنٹینر میں آخری اہم بٹس (ہمارے معاملے میں، عالمی پیلیٹ بائٹس) کو پوشیدہ پیغام کے بٹس سے تبدیل کرنے پر مشتمل ہے۔

پروگرام اس طریقہ کار کے حصے کے طور پر عالمی پیلیٹ بائٹس میں آخری دو بٹس استعمال کرے گا۔ اس کا مطلب یہ ہے کہ 24 بٹ امیج کے لیے، جہاں رنگ پیلیٹ سرخ، نیلے اور سبز کے لیے تین بائٹس کا ہے، اس میں پیغام کو سرایت کرنے کے بعد، ہر رنگ کا جز زیادہ سے زیادہ 3/255 گریڈیشنز سے بدل جائے گا۔ اس طرح کی تبدیلی، سب سے پہلے، نظر نہ آنے والی یا انسانی آنکھ کو محسوس کرنا مشکل ہو گا، اور دوم، یہ کم معیار کے معلوماتی آؤٹ پٹ آلات پر نظر نہیں آئے گا۔

معلومات کی مقدار کا براہ راست انحصار تصویری پیلیٹ کے سائز پر ہوگا۔ چونکہ پیلیٹ کا زیادہ سے زیادہ سائز 256 رنگوں کا ہے، اور اگر ہر رنگ کے جز میں دو میسج بٹس لکھے جائیں، تو پیغام کی زیادہ سے زیادہ لمبائی (تصویر میں زیادہ سے زیادہ پیلیٹ کے ساتھ) 192 بائٹس ہے۔ تصویر میں ایک بار پیغام سرایت کرنے کے بعد، فائل کا سائز تبدیل نہیں ہوتا ہے۔

پیلیٹ کی توسیع کا طریقہ، جو صرف GIF ڈھانچے کے لیے کام کرتا ہے۔ یہ چھوٹے پیلیٹ والی تصویروں پر سب سے زیادہ موثر ہوگا۔ اس کا جوہر یہ ہے کہ یہ پیلیٹ کے سائز کو بڑھاتا ہے، اس طرح کلر بائٹس کی جگہ ضروری بائٹس لکھنے کے لیے اضافی جگہ فراہم کرتا ہے۔ اگر ہم غور کریں کہ پیلیٹ کا کم از کم سائز 2 رنگ (6 بائٹس) ہے، تو ایمبیڈڈ پیغام کا زیادہ سے زیادہ سائز 256 × 3–6 = 762 بائٹس ہو سکتا ہے۔ اس کا نقصان کم کرپٹوگرافک سیکیورٹی ہے؛ ایمبیڈڈ پیغام کو کسی بھی ٹیکسٹ ایڈیٹر کا استعمال کرتے ہوئے پڑھا جا سکتا ہے اگر پیغام کو اضافی انکرپشن کا نشانہ نہ بنایا گیا ہو۔

عملی حصہ

پروگرام ڈیزائن

انکرپشن اور ڈکرپشن الگورتھم کو لاگو کرنے کے لیے تمام ضروری ٹولز پیکج میں شامل کیے جائیں گے۔ com.tsarik.steganography. اس پیکیج میں انٹرفیس شامل ہے۔ Encryptor طریقوں کے ساتھ encrypt и decrypt، کلاس Binary، جو بٹ arrays کے ساتھ ساتھ استثنائی کلاسوں کے ساتھ کام کرنے کی صلاحیت فراہم کرتا ہے۔ 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، بنیادی فرق پیلیٹ سے پیغام بائٹس لکھے اور پڑھے جانے کے طریقے میں ہے۔

پروگرام آپریشن

ایل بی ایس کا طریقہ

ہم کہتے ہیں کہ اس طرح کی ایک تصویر ہے:

GIF میں سٹیگنوگرافی

اس تصویر میں، پیلیٹ 256 رنگوں پر مشتمل ہے (جیسا کہ پینٹ محفوظ کرتا ہے)۔ پہلے چار رنگ ہیں: سفید، سیاہ، سرخ، سبز۔ دوسرے رنگ سیاہ ہیں۔ عالمی پیلیٹ بٹ کی ترتیب مندرجہ ذیل ہوگی:

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

GIF میں سٹیگنوگرافی

پیغام کے سرایت کرنے کے بعد، انڈر لائن کردہ بٹس کو پیغام کے بٹس سے بدل دیا جائے گا۔ نتیجے کی تصویر اصل سے تقریبا مختلف نہیں ہے.

حقیقی
ایمبیڈڈ پیغام کے ساتھ تصویر

GIF میں سٹیگنوگرافی
GIF میں سٹیگنوگرافی

پیلیٹ کی توسیع کا طریقہ

جب آپ اس طریقہ کو استعمال کرتے ہوئے پیغام پر مشتمل تصویر کھولیں گے تو آپ کو درج ذیل تصویر نظر آئے گی۔

GIF میں سٹیگنوگرافی

یہ واضح ہے کہ یہ طریقہ جاسوسی کی مکمل سرگرمیوں کے لیے کام نہیں کرے گا، اور اس کے لیے پیغام کے اضافی خفیہ کاری کی ضرورت پڑ سکتی ہے۔

اینی میٹڈ امیجز میں انکرپشن/ڈیکرپشن بالکل اسی طرح کام کرتا ہے جیسا کہ ریگولر سٹیٹک امیجز میں ہوتا ہے، لیکن اینیمیشن ٹوٹا نہیں ہے۔

استعمال شدہ ذرائع:

ڈاؤن لوڈ کریں:

ماخذ: www.habr.com

نیا تبصرہ شامل کریں