வாழ்த்துக்கள்.
மிக நீண்ட காலத்திற்கு முன்பு, நான் பல்கலைக்கழகத்தில் படிக்கும் போது, "தகவல் பாதுகாப்பிற்கான மென்பொருள் முறைகள்" என்ற பிரிவில் ஒரு பாடநெறி இருந்தது. GIF கோப்புகளில் ஒரு செய்தியை உட்பொதிக்கும் ஒரு நிரலை உருவாக்க வேண்டும். ஜாவாவில் செய்ய முடிவு செய்தேன்.
இந்த கட்டுரையில் நான் சில கோட்பாட்டு புள்ளிகளையும், இந்த சிறிய நிரல் எவ்வாறு உருவாக்கப்பட்டது என்பதையும் விவரிக்கிறேன்.
தத்துவார்த்த பகுதி
GIF வடிவம்
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 (குறைந்த முக்கியத்துவம் வாய்ந்த பிட்) முறை
தட்டு சேர்க்கும் முறை
LSB முறை - ஸ்டிகனோகிராஃபியின் பொதுவான முறை. இது கொள்கலனில் உள்ள கடைசி குறிப்பிடத்தக்க பிட்களை (எங்கள் விஷயத்தில், உலகளாவிய தட்டு பைட்டுகள்) மறைக்கப்பட்ட செய்தியின் பிட்களுடன் மாற்றுவதைக் கொண்டுள்ளது.
இந்த முறையின் ஒரு பகுதியாக உலகளாவிய தட்டு பைட்டுகளில் கடைசி இரண்டு பிட்களை நிரல் பயன்படுத்தும். அதாவது 24-பிட் படத்திற்கு, வண்ணத் தட்டு சிவப்பு, நீலம் மற்றும் பச்சை ஆகிய மூன்று பைட்டுகளாக இருக்கும், அதில் ஒரு செய்தியை உட்பொதித்த பிறகு, ஒவ்வொரு வண்ண கூறுகளும் அதிகபட்சமாக 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 வடிவமைப்பின் கட்டமைப்பின் அடிப்படையில், படத் தட்டுக்குள் ஒரு செய்தியை அறிமுகப்படுத்துவதற்கான பொதுவான வழிமுறையை நீங்கள் உருவாக்கலாம்:
ஒரு படத்தில் ஒரு செய்தி இருப்பதைத் தீர்மானிக்க, செய்தியின் தொடக்கத்தில் ஒரு குறிப்பிட்ட வரிசை பிட்களைச் சேர்க்க வேண்டியது அவசியம், அதை டிகோடர் முதலில் படித்து சரியானதா என்பதைச் சரிபார்க்கிறது. பொருந்தவில்லை என்றால், படத்தில் மறைக்கப்பட்ட செய்தி இல்லை என்று கருதப்படுகிறது. அடுத்து நீங்கள் செய்தியின் நீளத்தைக் குறிப்பிட வேண்டும். பின்னர் செய்தியின் உரை தானே.
முழு பயன்பாட்டின் வகுப்பு வரைபடம்:
திட்டத்தை செயல்படுத்துதல்
முழு நிரலையும் செயல்படுத்துவதை இரண்டு கூறுகளாகப் பிரிக்கலாம்: இடைமுக குறியாக்கம் மற்றும் மறைகுறியாக்க முறைகளை செயல்படுத்துதல் 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, செய்தி பைட்டுகள் தட்டிலிருந்து எழுதப்பட்டு படிக்கப்படும் விதத்தில் முக்கிய வேறுபாடு உள்ளது.
நிரல் செயல்பாடு
LBS முறை
இப்படி ஒரு படம் இருப்பதாக வைத்துக்கொள்வோம்.
இந்த படத்தில், தட்டு 256 வண்ணங்களைக் கொண்டுள்ளது (பெயிண்ட் சேமிக்கிறது). முதல் நான்கு வண்ணங்கள்: வெள்ளை, கருப்பு, சிவப்பு, பச்சை. மற்ற நிறங்கள் கருப்பு. உலகளாவிய தட்டு பிட் வரிசை பின்வருமாறு இருக்கும்: