ስቴጋኖግራፊ በጂአይኤፍ

መግቢያ

ሰላምታ.
ብዙም ሳይቆይ በዩኒቨርሲቲ ውስጥ በምማርበት ጊዜ “የመረጃ ደህንነት ሶፍትዌር ዘዴዎች” በሚለው ዲሲፕሊን ውስጥ የኮርስ ሥራ ነበር። ምደባው በጂአይኤፍ ፋይሎች ውስጥ መልእክትን የሚያካትት ፕሮግራም እንድንፈጥር አስፈልጎናል። በጃቫ ለማድረግ ወሰንኩ.

በዚህ ጽሑፍ ውስጥ አንዳንድ የንድፈ ሃሳቦችን እገልጻለሁ, እንዲሁም ይህ ትንሽ ፕሮግራም እንዴት እንደተፈጠረ.

ሥነ-መለኮታዊ ክፍል

GIF ቅርጸት

ጂአይኤፍ (የግራፊክስ መለዋወጫ ቅርጸት - ምስሎችን ለመለዋወጥ ቅርጸት) ግራፊክ ምስሎችን ለማከማቸት ቅርጸት ነው ፣ የታመቀ መረጃን ያለ ጥራት ማጣት እስከ 256 ቀለሞች ቅርጸት። ይህ ቅርጸት በ1987 (GIF87a) በCompuServe የራስተር ምስሎችን በኔትወርኮች ላይ ለማስተላለፍ ተዘጋጅቷል። በ 1989, ቅርጸቱ ተስተካክሏል (GIF89a), ግልጽነት እና አኒሜሽን ድጋፍ ታክሏል.

GIF ፋይሎች የማገጃ መዋቅር አላቸው። እነዚህ ብሎኮች ሁልጊዜ ቋሚ ርዝመት አላቸው (ወይንም በአንዳንድ ባንዲራዎች ላይ የተመሰረተ ነው), ስለዚህ እያንዳንዱ እገዳ የት እንደሚገኝ ስህተት ለመሥራት ፈጽሞ የማይቻል ነው. በGIF89a ቅርጸት በጣም ቀላሉ የማይንቀሳቀስ 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 ባይት ነው። መልእክቱ በምስሉ ውስጥ ከገባ በኋላ የፋይሉ መጠን አይለወጥም.

የፓለል ማስፋፊያ ዘዴለጂአይኤፍ መዋቅር ብቻ የሚሰራ። በትንሽ ቤተ-ስዕል ላይ ባሉ ምስሎች ላይ በጣም ውጤታማ ይሆናል. ዋናው ነገር የፓልቴል መጠኑን ይጨምራል, በዚህም በቀለም ባይት ምትክ አስፈላጊውን ባይት ለመጻፍ ተጨማሪ ቦታ ይሰጣል. የፓለቱ ዝቅተኛው መጠን 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.

በጂአይኤፍ ቅርፀት አወቃቀር ላይ በመመስረት መልእክትን ወደ ምስሉ ቤተ-ስዕል ለማስተዋወቅ አጠቃላይ ስልተ-ቀመር መፍጠር ይችላሉ-

ስቴጋኖግራፊ በጂአይኤፍ

በምስሉ ውስጥ የመልእክት መኖርን ለመወሰን በመልእክቱ መጀመሪያ ላይ የተወሰነ ተከታታይ ቢት ማከል አስፈላጊ ነው ፣ ይህም ዲኮደር መጀመሪያ ያነበበ እና ትክክለኛነትን ያረጋግጣል። የማይዛመድ ከሆነ በምስሉ ውስጥ ምንም የተደበቀ መልእክት እንደሌለ ይቆጠራል. በመቀጠል የመልእክቱን ርዝመት መግለጽ ያስፈልግዎታል. ከዚያ የመልእክቱ ጽሑፍ ራሱ።

የመተግበሪያው ክፍል ንድፍ፡-

ስቴጋኖግራፊ በጂአይኤፍ

የፕሮግራሙ ትግበራ

የጠቅላላው ፕሮግራም አተገባበር በሁለት ክፍሎች ሊከፈል ይችላል-የበይነገጽ ምስጠራ እና የዲክሪፕት ዘዴዎች ትግበራ Encryptor, በክፍል ውስጥ GIFEncryptorByLSBMethod и GIFEncryptorByPaletteExtensionMethod, እና የተጠቃሚ በይነገጽ ትግበራ.

ክፍሉን አስቡበት GIFEncryptorByLSBMethod.

ስቴጋኖግራፊ በጂአይኤፍ

መስኮች firstLSBit и secondLSBit መልእክቱ የሚገባበት እና መልእክቱ የሚነበብበት የእያንዳንዱን የምስሉ ባይት የቢት ቁጥሮች ይይዛል። መስክ checkSequence የተካተተውን መልእክት እውቅና ለማረጋገጥ የቼክ ቢት ቅደም ተከተል ያከማቻል። የማይንቀሳቀስ ዘዴ getEncryptingFileParameters የተገለጸውን ፋይል መለኪያዎች እና የመልዕክት ባህሪያትን ይመልሳል.

ዘዴ አልጎሪዝም encrypt ደረጃ GIFEncryptorByLSBMethod:

ስቴጋኖግራፊ በጂአይኤፍ

እና የእሱ ኮድ:

@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:

ስቴጋኖግራፊ በጂአይኤፍ

@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, ዋናው ልዩነቱ የመልእክት ባይት አጻጻፍ እና ከፓልቴል ውስጥ በሚነበብበት መንገድ ላይ ነው.

የፕሮግራም አሠራር

የኤል.ቢ.ኤስ ዘዴ

እንደዚህ ያለ ምስል አለ እንበል፡-

ስቴጋኖግራፊ በጂአይኤፍ

በዚህ ምስል, ቤተ-ስዕሉ 256 ቀለሞችን (እንደ ቀለም እንደሚያስቀምጥ) ያካትታል. የመጀመሪያዎቹ አራት ቀለሞች ነጭ, ጥቁር, ቀይ, አረንጓዴ ናቸው. ሌሎች ቀለሞች ጥቁር ናቸው. የአለምአቀፍ ቤተ-ስዕል ቢት ቅደም ተከተል እንደሚከተለው ይሆናል

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

ስቴጋኖግራፊ በጂአይኤፍ

መልእክቱ አንዴ ከገባ በኋላ የተሰመሩት ቢትስ ከመልእክቱ ቢትስ ይተካሉ። የተገኘው ምስል ከመጀመሪያው ፈጽሞ የተለየ አይደለም.

የመጀመሪያው
ምስል ከተከተተ መልእክት ጋር

ስቴጋኖግራፊ በጂአይኤፍ
ስቴጋኖግራፊ በጂአይኤፍ

የፓለል ማስፋፊያ ዘዴ

ይህንን ዘዴ ተጠቅመው መልእክት የያዘ ምስል ሲከፍቱ የሚከተለውን ምስል ያያሉ።

ስቴጋኖግራፊ በጂአይኤፍ

ይህ ዘዴ ሙሉ ለሙሉ የስለላ ስራዎች እንደማይሰራ ግልጽ ነው, እና ተጨማሪ የመልዕክት ምስጠራ ሊፈልግ ይችላል.

በአኒሜሽን ምስሎች ውስጥ ምስጠራ/ዲክሪፕት ማድረግ ልክ በመደበኛ ቋሚ ምስሎች ላይ ይሰራል፣ነገር ግን አኒሜሽኑ አልተሰበረም።

ያገለገሉ ምንጮች፡-

አውርድ:

ምንጭ: hab.com

አስተያየት ያክሉ