GIF හි Steganography

හැඳින්වීම

සුභ පැතුම්.
වැඩි කල් නොගොස්, මම විශ්ව විද්‍යාලයේ ඉගෙනුම ලබන විට, “තොරතුරු ආරක්‍ෂාව පිළිබඳ මෘදුකාංග ක්‍රම” විෂයයෙහි පා course මාලාවක් තිබුණි. පැවරුම අපට GIF ගොනු තුළ පණිවිඩයක් කාවැද්දූ වැඩසටහනක් නිර්මාණය කිරීමට අවශ්‍ය විය. මම එය ජාවා වලින් කිරීමට තීරණය කළෙමි.

මෙම ලිපියෙන් මම න්‍යායාත්මක කරුණු කිහිපයක් මෙන්ම මෙම කුඩා වැඩසටහන නිර්මාණය කළ ආකාරය විස්තර කරමි.

න්යායික කොටස

GIF ආකෘතිය

GIF (Graphics Interchange Format - පින්තූර හුවමාරු කිරීමේ ආකෘතියක්) යනු ග්‍රැෆික් රූප ගබඩා කිරීම සඳහා වන ආකෘතියකි, වර්ණ 256 දක්වා ආකෘතියකින් ගුණාත්මකභාවය නැතිවීමකින් තොරව සම්පීඩිත දත්ත ගබඩා කිරීමේ හැකියාව ඇත. මෙම ආකෘතිය 1987 (GIF87a) හි CompuServe විසින් ජාල හරහා රාස්ටර් රූප සම්ප්‍රේෂණය කිරීම සඳහා සංවර්ධනය කරන ලදී. 1989 දී, ආකෘතිය වෙනස් කරන ලදී (GIF89a), විනිවිදභාවය සහ සජීවිකරණය සඳහා සහය එක් කරන ලදී.

GIF ගොනු වල බ්ලොක් ව්‍යුහයක් ඇත. මෙම කුට්ටි සෑම විටම ස්ථාවර දිගක් ඇත (නැතහොත් එය සමහර ධජ මත රඳා පවතී), එබැවින් එක් එක් බ්ලොක් පිහිටා ඇති ස්ථානය පිළිබඳ වැරැද්දක් කිරීම පාහේ කළ නොහැක්කකි. GIF89a ආකෘතියෙන් සරලම සජීවීකරණය නොකළ GIF රූපයේ ව්‍යුහය:

GIF හි Steganography

ව්‍යුහයේ සියලුම කොටස් අතරින්, මෙම අවස්ථාවේ දී අපි ගෝලීය පැලට් බ්ලොක් එක සහ තාලයට වගකිව යුතු පරාමිතීන් ගැන උනන්දු වෙමු:

  • CT - ගෝලීය තලයක් තිබීම. මෙම ධජය සකසා ඇත්නම්, තාර්කික තිර හසුරුවෙන් පසු ගෝලීය තලය වහාම ආරම්භ විය යුතුය.
  • Size - palette විශාලත්වය සහ පින්තූරයේ ඇති වර්ණ ගණන. මෙම පරාමිතිය සඳහා අගයන්:

තරම
වර්ණ ගණන
පැලට් ප්‍රමාණය, බයිට්

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 ක්රමය - steganography පිළිබඳ පොදු ක්රමයකි. එය සමන්විත වන්නේ කන්ටේනරයේ ඇති අවසාන සැලකිය යුතු බිටු (අපගේ නඩුවේදී, ගෝලීය පැලට් බයිට්) සැඟවුණු පණිවිඩයේ බිටු සමඟ ප්‍රතිස්ථාපනය කිරීමෙනි.

වැඩසටහන මෙම ක්‍රමයේ කොටසක් ලෙස ගෝලීය පැලට් බයිට් වල අවසාන බිටු දෙක භාවිතා කරනු ඇත. මෙයින් අදහස් කරන්නේ, 24-bit රූපයක් සඳහා, වර්ණ පුවරුව රතු, නිල් සහ කොළ සඳහා බයිට් තුනක් වන අතර, එහි පණිවිඩයක් කාවැද්දීමෙන් පසු, එක් එක් වර්ණ සංරචක උපරිම වශයෙන් 3/255 ශ්‍රේණි වලින් වෙනස් වේ. එවැනි වෙනසක්, පළමුව, මිනිස් ඇසට නොපෙනෙන හෝ අපහසු වනු ඇත, දෙවනුව, එය අඩු ගුණාත්මක තොරතුරු ප්රතිදාන උපාංග මත නොපෙනේ.

තොරතුරු ප්‍රමාණය කෙලින්ම රූප පුවරුවේ ප්‍රමාණය මත රඳා පවතී. palette හි උපරිම ප්‍රමාණය වර්ණ 256 ක් වන අතර, එක් එක් වර්ණයෙහි සංරචකයට පණිවිඩ බිටු දෙකක් ලියා ඇත්නම්, උපරිම පණිවිඩ දිග (රූපයේ උපරිම palette සමඟ) බයිට් 192 කි. පණිවිඩය රූපයට ඇතුළත් කළ පසු, ගොනු ප්‍රමාණය වෙනස් නොවේ.

පැලට් පුළුල් කිරීමේ ක්රමය, GIF ව්‍යුහය සඳහා පමණක් ක්‍රියා කරයි. කුඩා තලයක් සහිත රූප මත එය වඩාත් ඵලදායී වනු ඇත. එහි සාරය නම්, එය palette ප්රමාණය වැඩි වන අතර, එමගින් වර්ණ බයිට් වෙනුවට අවශ්ය බයිට් ලිවීම සඳහා අමතර ඉඩක් ලබා දීමයි. palette හි අවම ප්‍රමාණය වර්ණ 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 හි Steganography

රූපයක පණිවිඩයක් තිබීම තීරණය කිරීම සඳහා, පණිවිඩයේ ආරම්භයට යම් බිටු අනුපිළිවෙලක් එක් කිරීම අවශ්‍ය වේ, එය විකේතකය පළමුව කියවා නිවැරදි දැයි පරීක්ෂා කරයි. එය නොගැලපේ නම්, රූපයේ සැඟවුණු පණිවිඩයක් නොමැති බව සලකනු ලැබේ. ඊළඟට ඔබ පණිවිඩයේ දිග සඳහන් කළ යුතුය. එවිට පණිවිඩයේම පෙළ.

සම්පූර්ණ යෙදුමේ පන්ති රූප සටහන:

GIF හි Steganography

වැඩසටහන ක්රියාත්මක කිරීම

සම්පූර්ණ වැඩසටහන ක්‍රියාත්මක කිරීම සංරචක දෙකකට බෙදිය හැකිය: අතුරුමුහුණත් සංකේතනය සහ විකේතන ක්‍රම ක්‍රියාත්මක කිරීම Encryptor, පන්ති වල GIFEncryptorByLSBMethod и GIFEncryptorByPaletteExtensionMethod, සහ පරිශීලක අතුරුමුහුණත ක්රියාත්මක කිරීම.

පන්තිය සලකා බලන්න GIFEncryptorByLSBMethod.

GIF හි Steganography

ක්ෂේත්ර firstLSBit и secondLSBit පණිවිඩය ඇතුළත් කළ යුතු සහ පණිවිඩය කියවිය යුතු රූපයේ එක් එක් බයිටයේ බිටු ගණන අඩංගු වේ. ක්ෂේත්රය checkSequence කාවැද්දූ පණිවිඩය හඳුනා ගැනීම සහතික කිරීම සඳහා චෙක් බිට් අනුපිළිවෙලක් ගබඩා කරයි. ස්ථිතික ක්රමය getEncryptingFileParameters නිශ්චිත ගොනුවේ පරාමිතීන් සහ විභව පණිවිඩයේ ලක්ෂණ ආපසු ලබා දෙයි.

ක්රම ඇල්ගොරිතම encrypt පන්ති GIFEncryptorByLSBMethod:

GIF හි Steganography

සහ ඔහුගේ කේතය:

@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 හි Steganography

@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, ප්‍රධාන වෙනස වන්නේ පණිවිඩ බයිට් ලියන ආකාරය සහ palette වෙතින් කියවන ආකාරයයි.

වැඩසටහන් මෙහෙයුම

LBS ක්රමය

මේ වගේ රූපයක් තියෙනවා කියමු.

GIF හි Steganography

මෙම රූපයේ, palette වර්ණ 256 කින් සමන්විත වේ (තීන්ත සුරකින පරිදි). පළමු වර්ණ හතර: සුදු, කළු, රතු, කොළ. අනෙකුත් වර්ණ කළු ය. ගෝලීය palette bit අනුපිළිවෙල පහත පරිදි වනු ඇත:

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

GIF හි Steganography

පණිවිඩය කාවැද්දූ පසු, යටින් ඉරි ඇඳ ඇති බිටු පණිවිඩයේ ඇති බිටු සමඟ ප්‍රතිස්ථාපනය වේ. ප්රතිඵලයක් වශයෙන් රූපය මුල් පිටපතට වඩා වෙනස් නොවේ.

මුල් පිටපත
කාවැද්දූ පණිවිඩයක් සහිත රූපය

GIF හි Steganography
GIF හි Steganography

පැලට් පුළුල් කිරීමේ ක්රමය

ඔබ මෙම ක්‍රමය භාවිතා කර පණිවිඩයක් සහිත පින්තූරයක් විවෘත කළ විට, ඔබට පහත පින්තූරය පෙනෙනු ඇත:

GIF හි Steganography

මෙම ක්‍රමය පූර්ණ ඔත්තු බැලීමේ ක්‍රියාකාරකම් සඳහා ක්‍රියා නොකරනු ඇති බව පැහැදිලිය, තවද පණිවිඩයේ අතිරේක සංකේතනය අවශ්‍ය විය හැකිය.

සාමාන්‍ය ස්ථිතික රූපවල මෙන් සජීවිකරණ රූපවල සංකේතනය/විකේතනය ක්‍රියා කරයි, නමුත් සජීවිකරණය කැඩී නැත.

භාවිතා කරන ලද මූලාශ්ර:

බාගත කිරීම:

මූලාශ්රය: www.habr.com

අදහස් එක් කරන්න