Gaisuwa.
Ba da dadewa ba, lokacin da nake karatu a jami'a, akwai aikin kwas a cikin horo "Hanyoyin Tsaro na Software." Aikin ya buƙaci mu ƙirƙiri shirin da ke haɗa saƙo a cikin fayilolin GIF. Na yanke shawarar yin shi a Java.
A cikin wannan labarin zan bayyana wasu batutuwa na ka'idar, da kuma yadda aka ƙirƙiri wannan ƙaramin shirin.
Bangaren ilimi
Tsarin GIF
GIF (Tsarin Musanyar Hotuna - Tsarin musayar hotuna) tsari ne na adana hotuna masu hoto, mai ikon adana bayanan da aka matsa ba tare da asarar inganci ba a cikin sigar har zuwa launuka 256. An ƙirƙira wannan tsari a cikin 1987 (GIF87a) ta CompuServe don watsa hotunan raster akan cibiyoyin sadarwa. A cikin 1989, an gyaggyara tsarin (GIF89a), an ƙara tallafi don nuna gaskiya da raye-raye.
Fayilolin GIF suna da tsarin toshewa. Wadannan tubalan ko da yaushe suna da tsayayyen tsayi (ko ya dogara da wasu tutoci), don haka kusan ba zai yuwu a yi kuskure game da inda kowane shinge yake ba. Tsarin mafi sauƙin hoton GIF mara rai a cikin tsarin GIF89a:
Daga cikin dukkan tubalan tsarin, a cikin wannan yanayin za mu yi sha'awar toshe palette na duniya da sigogi da ke da alhakin palette:
CT - kasancewar palette na duniya. Idan an saita wannan tuta, palette ɗin duniya dole ne ya fara nan da nan bayan rikon allo mai ma'ana.
Size - Girman palette da adadin launuka a cikin hoton. Ƙimar wannan siga:
size
Yawan launuka
Girman palette, bytes
7
256
768
6
128
384
5
64
192
4
32
96
3
16
48
2
8
24
1
4
12
0
2
6
Hanyoyin ɓoyewa
Za a yi amfani da hanyoyi masu zuwa don ɓoye saƙonni a cikin fayilolin hoto:
Hanyar LSB (Mafi Muhimmanci Bit).
Hanyar ƙara palette
Hanyar LSB - hanyar gama gari na steganography. Ya ƙunshi maye gurbin mahimman rago na ƙarshe a cikin akwati (a cikin yanayinmu, baiti na palette na duniya) tare da ɓoyayyun saƙon.
Shirin zai yi amfani da rago biyu na ƙarshe a cikin palette bytes na duniya a matsayin wani ɓangare na wannan hanya. Wannan yana nufin cewa ga hoton 24-bit, inda palette mai launi ya kasance bytes uku don ja, blue, da kore, bayan shigar da saƙo a cikinsa, kowane ɓangaren launi zai canza da iyakar 3/255 gradations. Irin wannan canjin, na farko, zai zama marar ganuwa ko wuyar ganewa ga idon ɗan adam, na biyu kuma, ba za a iya gani a kan ƙananan na'urorin fitar da bayanai ba.
Adadin bayanin zai dogara kai tsaye akan girman palette na hoto. Tun da matsakaicin girman palette shine launuka 256, kuma idan an rubuta ragowar saƙo guda biyu a cikin ɓangaren kowane launi, to matsakaicin tsayin saƙo (tare da matsakaicin palette a cikin hoton) shine 192 bytes. Da zarar an saka saƙon a cikin hoton, girman fayil ɗin ba ya canzawa.
Hanyar fadada palette, wanda kawai ke aiki don tsarin GIF. Zai zama mafi tasiri akan hotuna tare da ƙananan palette. Mahimmancinsa shine yana ƙara girman palette, ta haka yana samar da ƙarin sarari don rubuta abubuwan da suka dace a maimakon launi na launi. Idan muka yi la'akari da cewa mafi ƙarancin girman palette shine launuka 2 (6 bytes), to, matsakaicin girman saƙon da aka saka zai iya zama 256 × 3–6 = 762 bytes. Rashin lahani shine ƙarancin tsaro na sirri; ana iya karanta saƙon da aka haɗa ta amfani da kowane editan rubutu idan ba a shigar da saƙon zuwa ƙarin ɓoyewa ba.
Sashi mai amfani
Tsarin shirin
Duk kayan aikin da ake buƙata don aiwatar da ɓoyayyen ɓoyewa da ɓangarorin ɓarna za a haɗa su a cikin kunshin com.tsarik.steganography. Wannan fakitin ya haɗa da abin dubawa Encryptor tare da hanyoyin encrypt и decrypt, Darasi Binary, wanda ke ba da damar yin aiki tare da raƙuman ruwa, da kuma azuzuwan ban da UnableToEncryptException и UnableToDecryptException, wanda ya kamata a yi amfani da shi a cikin hanyoyin sadarwa Encryptor idan akwai kurakurai na ɓoyewa da yanke hukunci.
Babban kunshin shirin com.tsarik.programs.gifed zai haɗa da ajin shirye-shirye masu gudana tare da tsayayyen hanya main, ba ka damar gudanar da shirin; aji wanda ke adana sigogin shirye-shirye; da fakiti tare da sauran azuzuwan.
Za a gabatar da aiwatar da algorithms kansu a cikin kunshin com.tsarik.programs.gifed.gif azuzuwan GIFEncryptorByLSBMethod и GIFEncryptorByPaletteExtensionMethod. Duk waɗannan azuzuwan za su aiwatar da hanyar sadarwa Encryptor.
Dangane da tsarin tsarin GIF, zaku iya ƙirƙirar algorithm na gaba ɗaya don gabatar da saƙo a cikin palette ɗin hoto:
Don tantance kasancewar saƙo a cikin hoto, dole ne a ƙara wasu jeri na bits zuwa farkon saƙon, wanda mai yankewa ya fara karantawa kuma ya bincika daidai. Idan bai dace ba, to ana la'akari da cewa babu wani ɓoye a cikin hoton. Na gaba kuna buƙatar tantance tsawon saƙon. Sai rubutun sakon da kansa.
Jadawalin aji na aikace-aikacen duka:
Aiwatar da shirin
Ana iya raba aiwatar da shirin gabaɗaya zuwa sassa biyu: aiwatar da ɓoyayyen ɓoyewa da hanyoyin ɓoye bayanan Encryptor, a cikin azuzuwan GIFEncryptorByLSBMethod и GIFEncryptorByPaletteExtensionMethod, da kuma aiwatar da haɗin gwiwar mai amfani.
Yi la'akari da aji GIFEncryptorByLSBMethod.
filayen firstLSBit и secondLSBit yana dauke da lambobi na kowane byte na hoton da ya kamata a shigar da sakon kuma daga inda ya kamata a karanta saƙon. Filin checkSequence tana adana jerin gwano don tabbatar da gane saƙon da aka haɗa. Hanyar a tsaye getEncryptingFileParameters yana dawo da sigogi na ƙayyadaddun fayil da halayen saƙon mai yuwuwa.
@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();
}
Algorithm da lambar tushe na hanyar decrypt aji 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);
}
Aiwatar da aji GIFEncryptorByPaletteExtensionMethod zai zama kama, kawai hanyar adanawa / karanta bayanai ya bambanta.
A cikin aji MainFrame An bayyana hanyoyin kunsa: encryptImage(Encryptor encryptor) и decryptImage(Encryptor encryptor), sarrafa sakamakon hanyoyin sadarwa Encryptor da yin hulɗa tare da mai amfani, watau buɗe maganganun zaɓin fayil, nuna saƙonnin kuskure, da sauransu; da sauran hanyoyin: openImage(), kyale mai amfani ya zaɓi hoto, exit(), wanda ke fita aikace-aikacen. Ana kiran waɗannan hanyoyin daga Actionabubuwan menu masu dacewa. Hakanan wannan ajin yana aiwatar da hanyoyin taimako: createComponents() - ƙirƙirar abubuwan da aka gyara, loadImageFile(File f) - loda hoto zuwa wani yanki na musamman daga fayil. Aiwatar da aji GIFEncryptorByPaletteExtensionMethod kama da aiwatar da aji GIFEncryptorByLSBMethod, Babban bambanci shine yadda ake rubuta bytes na saƙo da karantawa daga palette.
Ayyukan shirin
Hanyar LBS
Bari mu ce akwai hoto kamar haka:
A cikin wannan hoton, palette ɗin ya ƙunshi launuka 256 (kamar yadda Paint ke adanawa). Launuka huɗu na farko sune: fari, baƙi, ja, kore. Sauran launuka baƙar fata ne. Jerin bit palette na duniya zai kasance kamar haka:
Da zarar an shigar da saƙon, za a maye gurbin raƙuman raƙuman da aka ja layi tare da ragowa daga saƙon. Hoton da aka samu kusan bai bambanta da na asali ba.
Asali
Hoto mai kunshe da saƙo
Hanyar fadada palette
Lokacin da ka bude hoto mai dauke da sako ta amfani da wannan hanya, za ka ga hoton kamar haka:
A bayyane yake cewa wannan hanyar ba za ta yi aiki don cikakkun ayyukan leƙen asiri ba, kuma tana iya buƙatar ƙarin ɓoyayyen saƙon.
Rufewa/rushewa a cikin hotuna masu rai yana aiki kamar a cikin hotuna na yau da kullun, amma rayarwa ba ta karye ba.